1. 程式人生 > >周二上午

周二上午

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>
 2
using 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
View Code

最後一題有些難度吧,感覺主要是轉換,(精度怎麽還是不過

稍微有點長,但是概率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

周二上午