2017寒假概率dp训练题

poj 3744 Scout YYF I    

简单题,不难找到递推,设dp[i]为安全达到i的概率,dp[0]=0,dp[1]=1,dp[i]=p*dp[i-1]+(1-p)*dp[i-2],用矩阵快速幂计算,再相乘.

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int N;double p;
 6 int a[15];
 7 struct matrix{
 8     double a[2][2];
 9 };
10 matrix muti(matrix x,matrix y){
11     matrix t;
12     for(int i=0;i<2;++i){
13         for(int j=0;j<2;++j){
14             t.a[i][j]=0;//init
15             for(int k=0;k<2;++k){
16                 t.a[i][j]+=1.0*x.a[i][k]*y.a[k][j];
17             }
18         }
19     }
20     return t;
21 }
22 double getP(int n){
23     matrix ans,base;
24     ans.a[0][0]=1;ans.a[0][1]=ans.a[1][0]=ans.a[1][1]=0;
25     base.a[0][0]=p;base.a[0][1]=1-p;base.a[1][0]=1.0;base.a[1][1]=0.0;
26     if(n<0)return 0;
27     while(n){
28     //    printf("n=%d\n",n);
29         if(n&1)ans=muti(base,ans);
30         base=muti(base,base);
31         n/=2;
32     }
33     return ans.a[0][0];
34 }
35 int main(){
36     while(~scanf("%d%lf",&N,&p)){
37         for(int i=0;i<N;++i){
38             scanf("%d",&a[i]);
39         }
40         sort(a,a+N);
41         double res=1.0;
42         int prev=1;
43         for(int i=0;i<N;++i){
44             res=res*(1-p)*getP(a[i]-prev-1);
45             prev=a[i]+1;
46         }
47         printf("%.7f\n",res);
48     }
49     return 0;
50 }
View Code

 cf148D

题目链接:http://codeforces.com/problemset/problem/148/D

简单题,我是写的记忆化搜索,但开始在巨龙的公式那出了问题,花了两个多小时.

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 const int MAXN=1007;
 4 double dp[MAXN][MAXN][2];
 5 int visit[MAXN][MAXN][2];
 6 //0 is princess,1 is dragon
 7 double dfs(int w,int b,int status){
 8     //printf("w=%d,b=%d,status=%d\n",w,b,status);
 9     if(w<=0){
10          dp[0][b][1]=1.0;
11          dp[0][b][0]=0.0;
12          return dp[0][b][status];
13     }
14     if(b<=0){
15         dp[w][0][status]=1.0;
16         dp[w][0][1-status]=0.0;
17         return dp[w][0][status];
18     }
19     if(visit[w][b][status])return dp[w][b][status];
20     visit[w][b][status]=1;
21     double res=w*1.0/(w+b);
22     if(status==0){
23         res+=b*1.0/(w+b)* (1.0-dfs(w,b-1,1));
24     }else{
25         res+=b*1.0/(w+b)* (((w*1.0/(w+b-1)*(1-dfs(w-1,b-1,0)))) + ((b-1)*1.0/(w+b-1)*(1-dfs(w,b-2,0))));
26     }
27     dp[w][b][status]=res;
28     //printf("dp[%d][%d][%d]=%.9f\n",w,b,status,res);
29     return dp[w][b][status];
30 }
31 int main(){
32     int w,b;
33     scanf("%d%d",&w,&b);
34     memset(visit,0,sizeof(visit));
35     printf("%.10f\n",dfs(w,b,0));
36     return 0;
37 }
View Code

 hdoj4405 飞行棋

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4405

期望入门题,问达到终点期望投多少次骰子.

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 const int MAXN=2e5+7,MAXM=1e3+7;
 4 double dp[MAXN];
 5 int fly[MAXN];
 6 int main(){
 7     int N,M;
 8     while(scanf("%d%d",&N,&M)&&N+M){
 9         memset(fly,0,sizeof(fly));
10         memset(dp,0,sizeof(dp));
11         for(int i=0;i<M;++i){
12             int a,b;scanf("%d%d",&a,&b);
13             fly[a]=b;
14         }
15         dp[N]=0;
16         for(int i=N-1;i>=0;--i){
17             if(fly[i]==0){
18                 for(int x=1;x<=6;++x){
19                     dp[i]+=1.0/6*dp[i+x];
20                 }
21                 dp[i]++;
22             }
23             else dp[i]=dp[fly[i]];
24         }
25         printf("%.4f\n",dp[0]);
26     }
27     return 0;
28 }
View Code

 

posted on 2018-01-29 21:52  Na_OH  阅读(120)  评论(0编辑  收藏  举报

导航