概率DP

 http://blog.csdn.net/auto_ac/article/details/9907881

Scout YYF I

 POJ - 3744 

题意:起点是1,有n个点有地雷,问顺利通过的概率。

按地雷分段,求每一段踩到雷的概率p,那么1-p就是通过该段的概率,然后乘法原理每段概率相乘。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxn=2;
 7 struct Matrix{
 8     int n;
 9     double m[maxn][maxn];
10 
11     void init(int sz){
12         n=sz;
13         memset(m,0,sizeof(m));
14     }
15     Matrix(int sz){
16         init(sz);
17     }
18     void setI(){
19         for(int i=0;i<n;i++) m[i][i]=1;
20     }
21 
22     Matrix operator* (const Matrix& a){
23         Matrix res(n);
24         for(int k=0;k<n;k++)
25             for(int i=0;i<n;i++)
26                 for(int j=0;j<n;j++)
27                     res.m[i][j]+=m[i][k]*a.m[k][j];
28         return res;
29     }
30 };
31 double quickpow(Matrix b,int n){
32     Matrix a(2);
33     a.setI();
34     while(n){
35         if(n&1) a=a*b;
36         b=b*b;
37         n>>=1;
38     }
39     return 1-a.m[0][0];
40 }
41 int x[15];
42 int main(){
43     int n;
44     double p;
45     x[0]=0;
46     while(scanf("%d%lf",&n,&p)!=EOF){
47         n++;
48         for(int i=1;i<n;i++) scanf("%d",&x[i]);
49         sort(x,x+n);
50         double ans=1;
51         Matrix b(2);
52         b.m[0][0]=p;b.m[0][1]=1-p;
53         b.m[1][0]=1;
54         for(int i=1;i<n;i++){
55             //if(x[i]==x[i-1]+1){ans=0;break;}  
56             ans*=quickpow(b,x[i]-x[i-1]-1);
57         }
58         printf("%.7f
",ans);  //!!poj用%f
59     }
60 }
View Code

LOOPS

 HDU - 3853 

题意:求从[1,1]走到[r,c]需要的魔力值。三种走法对应不同概率,每一步消耗2魔力值。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn=1010;
 5 double p[maxn][maxn][3];
 6 double dp[maxn][maxn];
 7 
 8 int main(){
 9     int r,c;
10     while(scanf("%d%d",&r,&c)!=EOF){
11         for(int i=0;i<r;i++)
12             for(int j=0;j<c;j++)
13                 for(int k=0;k<3;k++)
14                     scanf("%lf",&p[i][j][k]);
15         r--;c--;
16         dp[r][c]=0;
17         for(int i=r;i>=0;i--){
18             for(int j=c;j>=0;j--){
19                 if(p[i][j][0]==1||i==r&&j==c) continue;
20                 dp[i][j]=(p[i][j][1]*dp[i][j+1]+p[i][j][2]*dp[i+1][j]+2)/(1-p[i][j][0]);
21             }
22         }
23         printf("%.3lf
",dp[0][0]);
24     }
25     return 0;
26 }
View Code

Aeroplane chess

 HDU - 4405 

题意:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn=100010;
 5 double dp[maxn];
 6 int fly[maxn];
 7 
 8 int main(){
 9     int n,m;
10     while(scanf("%d%d",&n,&m)&&(n||m)){
11         memset(dp,0,sizeof(dp));
12         memset(fly,0,sizeof(fly));
13         int u,v;
14         for(int i=0;i<m;i++){
15             scanf("%d%d",&u,&v);
16             fly[u]=v;
17         }
18         for(int i=n-1;i>=0;i--){
19             if(fly[i]) dp[i]=dp[fly[i]];
20             else{
21                 for(int j=1;j<=6;j++){
22                     if(i+j>=n) dp[i]+=1.0/6*dp[n];
23                     else dp[i]+=1.0/6*dp[i+j];
24                 }
25                 dp[i]++;
26             }
27         }
28         printf("%.4lf
",dp[0]);
29     }
30     return 0;
31 }
View Code

Football

 POJ - 3071 

题意:

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 const int maxn=150;
 6 double p[maxn][maxn];
 7 double dp[maxn][maxn];
 8 
 9 int main(){
10     int n;
11     while(scanf("%d",&n)&&n!=-1){
12         int num=1<<n;
13         for(int i=0;i<num;i++)
14             for(int j=0;j<num;j++)
15                 scanf("%lf",&p[i][j]);
16         memset(dp,0,sizeof(dp));
17         for(int i=0;i<num;i++) dp[0][i]=1;
18         for(int i=1;i<=n;i++){
19             for(int j=0;j<num;j++)
20             for(int k=0;k<num;k++){
21                 if(j>>(i-1)==((k>>(i-1))^1)) dp[i][j]+=dp[i-1][j]*(dp[i-1][k]*p[j][k]);
22             }
23         }
24         int ans=0;
25         for(int i=1;i<num;i++){
26             if(dp[n][i]>dp[n][ans]) ans=i;
27         }
28         printf("%d
",ans+1);
29     }
30     return 0;
31 }
View Code

One Person Game

 ZOJ - 3329 

题意:有三个骰子,分别有k1,k2,k3个面。每次掷骰子,如果三个面分别为a,b,c则分数置0,否则加上三个骰子的分数之和。当分数大于n时结束。求游戏的期望步数。初始分数为0

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=610;
 4 int n,k1,k2,k3,a,b,c;
 5 double p[66];
 6 double A[maxn],B[maxn];
 7 int main(){
 8     int t;
 9     scanf("%d",&t);
10     while(t--){
11         scanf("%d%d%d%d%d%d%d",&n,&k1,&k2,&k3,&a,&b,&c);
12         memset(p,0,sizeof(p));
13         double p0=1.0/k1/k2/k3;
14         for(int i=1;i<=k1;i++)
15         for(int j=1;j<=k2;j++)
16         for(int k=1;k<=k3;k++){
17             if(i!=a||j!=b||k!=c) p[i+j+k]+=p0;
18         }
19         memset(A,0,sizeof(A));
20         memset(B,0,sizeof(B));
21         for(int i=n;i>=0;i--){
22             A[i]=p0;B[i]=1;
23             for(int j=1;j<=k1+k2+k3;j++){
24                 A[i]+=A[i+j]*p[j];
25                 B[i]+=B[i+j]*p[j];
26             }
27         }
28         printf("%.16lf
",B[0]/(1-A[0]));
29     }
30 }
View Code

Bag of mice

 CodeForces - 148D

题意:王子公主抓老鼠。。。公主先抓,每次王子抓完就会随机跑掉一只,谁先抓到白老鼠就获胜。

记忆化搜索

 1 #include<bits/stdc++.h>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define P pair<int ,int >
 5 using namespace  std;
 6 const int maxn=1010;
 7 int w,b;
 8 map<P ,double >memo;
 9 
10 double win(int w,int b)
11 {
12     if(w<=0) return 0;
13     if(b<=0) return 1;
14     P args(w,b);
15     if(memo.find(args)!=memo.end())
16         return memo[args];
17     double res=w*1.0/(w+b);
18     double temp=b*1.0/(w+b);
19     b--;
20     temp*=b*1.0/(w+b);
21     b--;
22     if(temp>1e-10)
23     {
24         double brun=win(w,b-1)*b*1.0/(w+b);
25         double wrun=win(w-1,b)*w*1.0/(w+b);
26         res+=temp*(brun+wrun);
27     }
28     memo[args]=res;
29         return res;
30 }
31 int main()
32 {
33     cin>>w>>b;
34     double ans=win(w,b);
35     printf("%.9lf
",ans);
36 }
View Code

Time travel

 HDU - 4418

原文地址:https://www.cnblogs.com/yijiull/p/7357802.html