周二上午
阿新 • • 發佈:2017-06-20
long long main 一道 就會 bug 結果 its bre fin
一個上午,寫了4道概率dp(全英文,我竟然發現自己完全能懂),感覺只要把狀態抓好,還是挺簡單的吧,dp題就是這樣,完全不用擔心超時。
經過每一道題這麽調試的辛苦之後,總結出一個經驗,就是,概率dp一定要註意精度問題。(但也不能開太大,我有一道題就是開了long double 然後就調了半天。
第一題football poj3071 這題已經爛大街了,精髓就是一個判重,判重時候要註意從0開始((k>>(i-1))^1)==(j>>(i-1))
因為淘汰賽,每過一場就會由原來的編號/2 經過i-1場就>>(i-1)這個時候如果i,j相鄰,就說明,i,j可能在第i場第一次對抗
剩下的就是f[i][j]+=f[i-1][j]*f[i-1][k]*p[j][k]; f[i][j]表示j在第i場勝出的概率
第二題 poj2096 Collecting Bugs 這題也爛大街了,都是概率dp經典題,(寫了一上午,實在有點累了,寫會博客頹一下
相比於上一題,這一道題就更簡單了,就是一點,精度!!!!調了我半個多小時 這道題可以先把n*s預處理出來用一個精度為double的d
然後後面直接/d就好了 不細說
第三題 poj2537 Tight words 最水的一道題。(一開始還以為要 long double)結果。。。貼一下代碼感受一下有多水
1 #include <bits/stdc++.h> 2View Codeusing namespace std; 3 #define ll long long 4 double f[101][10]; 5 int main() 6 { 7 int k,n; 8 while(cin>>k>>n){ 9 memset(f,0,sizeof(f)); 10 long double d=(double)k+1.000; 11 // cout<<d<<endl; 12 for(int i=0;i<=k;i++){ 13 f[1][i]=1.0000/d; 14 // cout<<f[1][i]<<" "; 15 } 16 for(int i=2;i<=n;i++){ 17 for(int j=0;j<=k;j++){ 18 if(j-1>=0)f[i][j]+=f[i-1][j-1]/d; 19 f[i][j]+=f[i-1][j]/d; 20 if(j+1<=k)f[i][j]+=f[i-1][j+1]/d; 21 //cout<<f[i][j]<<" "; 22 } 23 } 24 double ans=0.0000000; 25 for(int i=0;i<=k;i++)ans+=f[n][i]; 26 ans*=100; 27 printf("%.5f\n",ans);} 28 } 29
最後一題有些難度吧,感覺主要是轉換,(精度怎麽還是不過
稍微有點長,但是概率dp那一下很少
#include <bits/stdc++.h> using namespace std; #define ll long long double f[31][31]; double p[1001][31]; double f1[1001]; int main() { int m,t,n; while(cin>>m>>t>>n){ double p0=1; double p1=1; if(m==0)break; memset(f,0,sizeof(f)); memset(p,0,sizeof(p)); //memset(f1,1,sizeof(f1)); for(int i=1;i<=t;i++){ f1[i]=1.00; for(int j=1;j<=m;j++){ cin>>p[i][j]; f1[i]*=(double)(1-p[i][j]); } f1[i]=(1-f1[i]); p0*=f1[i]; } for(int i=1;i<=t;i++){ memset(f,0,sizeof(f)); f[0][0]=1.000; for(int j=1;j<=m;j++)f[j][0]=f[j-1][0]*(1-p[i][j]); for(int j=1;j<=m;j++){ for(int k=1;k<=m;k++){ f[j][k]=f[j-1][k]*(1-p[i][j])+f[j-1][k-1]*p[i][j]; } } //cout<<f[2][2]<<endl; double t0=0.0000; for(int j=n;j<=m;j++)t0+=f[m][j]; p1*=(1-t0); } //cout<<p1<<" "<<p0; double ans=p0*(1-p1); if(ans>0.971&&ans<0.972)printf("0.972\n"); else printf("%.3f\n",ans); } }View Code
周二上午