期望DP

BZOJ 1415

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cstdio>
 5 using namespace std;
 6 const int Maxn=1010;
 7 int t[Maxn],n,m,S,T,now,p[Maxn][Maxn],head[Maxn],dis[Maxn],u,v,cnt;
 8 double f[Maxn][Maxn];
 9 struct EDGE
10 {
11     int to,next;
12 }edge[Maxn<<2];
13 inline void Add(int u,int v)
14 {edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}
15 void Dfs(int u,int top)
16 {
17     for (int i=head[u];i!=-1;i=edge[i].next)
18         if (dis[edge[i].to]==-1 || dis[edge[i].to]>dis[u]+1 || (dis[edge[i].to]==dis[u]+1 && p[now][edge[i].to]>top))
19         {
20             dis[edge[i].to]=dis[u]+1;
21             p[now][edge[i].to]=top;
22             Dfs(edge[i].to,top);
23         }
24 }
25 double F(int S,int T)
26 {
27     if (f[S][T]!=0) return f[S][T];
28     if (S==T) return 0;
29     if (p[p[S][T]][T]==T || p[S][T]==T) return 1;
30     double res=0;
31     for (int i=head[T];i!=-1;i=edge[i].next)
32         res+=F(p[p[S][T]][T],edge[i].to);
33     res+=F(p[p[S][T]][T],T); 
34     res/=(double)(t[T]+1.0);
35     res+=1;
36     return f[S][T]=res;
37 }
38 int main()
39 {
40     scanf("%d%d",&n,&m);
41     scanf("%d%d",&S,&T);
42     memset(head,-1,sizeof(head));
43     for (int i=1;i<=m;i++)
44     {
45         scanf("%d%d",&u,&v);
46         Add(u,v),Add(v,u);
47         t[u]++; t[v]++;
48     }
49      
50     for (int i=1;i<=n;i++) 
51     {
52         memset(dis,-1,sizeof(dis));
53         dis[i]=0;
54         for (int j=head[i];j!=-1;j=edge[j].next)
55         {
56             now=i;
57             dis[edge[j].to]=1;
58             Dfs(edge[j].to,edge[j].to);
59         }
60         for (int j=head[i];j!=-1;j=edge[j].next) p[i][edge[j].to]=edge[j].to;
61     }
62     printf("%.3lf
",F(S,T));
63     return 0;
64 }
C++

BZOJ 1419

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 using namespace std;
 6 const int Maxn=5010;
 7 double f[3][Maxn];
 8 int R,B,cur;
 9 inline double Max(double x,double y) {return x>y?x:y;}
10 int main()
11 {
12     scanf("%d%d",&R,&B);
13     for (int i=1;i<=R;i++)
14     {
15         cur^=1;
16         for (int j=0;j<=B;j++)
17         {
18             if (i==0) {f[cur][j]=0; continue;}
19             if (j==0) {f[cur][j]=f[cur^1][j]+1;continue;}
20             f[cur][j]=Max(0,(f[cur^1][j]+1.0)*((double)(i)/(double)(i+j))+(f[cur][j-1]-1.0)*((double)(j)/(double)(i+j)));
21  
22         }
23     }
24     printf("%.6lf
",f[cur][B]-5e-7);
25     return 0;
26 }
C++

算法合集之《浅析竞赛中一类数学期望问题的解决方法》中有对题目的讲解。

HDU 4405 期望貌似是倒着推的,F[i]=∑F[i+k](k=1~6) /6+1;  但因为又加了一步所以要加一。可以直接跳到的则期望是一样的。

 1 #include <cstdio>
 2 #include <cstring>
 3 const int Maxn=100100;
 4 int vis[Maxn],n,m,u,v;
 5 double F[Maxn];
 6 int main()
 7 {
 8     while (scanf("%d%d",&n,&m)!=EOF)
 9     {
10         if (n==0 && m==0) break;
11         memset(vis,-1,sizeof(vis));
12         for (int i=1;i<=m;i++) scanf("%d%d",&u,&v),vis[u]=v;
13         memset(F,0,sizeof(F));
14         for (int i=n-1;i>=0;i--)
15             if (vis[i]==-1)
16             {
17                 for (int j=1;j<=6;j++) F[i]+=F[i+j]/6.0;
18                 F[i]=F[i]+1;
19             } else 
20                 F[i]=F[vis[i]];
21         printf("%.4lf
",F[0]);
22     }
23     return 0;
24 }
C++

HDU 4089 至今还不是很清楚怎么退的。。

 1 #include <cstdio>
 2 const int Maxn=2010;
 3 const double eps=1e-5;
 4 double F[Maxn][Maxn],p1,p2,p3,p4,x[Maxn],z[Maxn];
 5 int n,m,k;
 6 int main()
 7 {
 8     while (scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p1,&p2,&p3,&p4)!=EOF)
 9     {
10         if (p4<eps)    {puts("0.00000");continue;}
11         double p21=p2/(1-p1),p31=p3/(1-p1),p41=p4/(1-p1);
12         F[1][1]=p4/(1-p2-p1);
13         for (int i=2;i<=n;i++)
14         {
15             x[1]=p21; z[1]=p41;
16             for (int j=2;j<=i;j++)
17             {
18                 x[j]=x[j-1]*p21;
19                 z[j]=p31*F[i-1][j-1]+p21*z[j-1];
20                 if (j<=k) z[j]+=p41;
21             }
22             F[i][i]=z[i]/(1-x[i]);
23             for (int j=1;j<i;j++) F[i][j]=x[j]*F[i][i]+z[j];
24         }
25         printf("%.5lf
",F[n][m]);
26     }
27     return 0;
28 }
C++

POJ 2096 一直末状态推终状态。

 1 #include<cstdio>
 2 const int Maxn=1010;
 3 double F[Maxn][Maxn];
 4 int n,s;
 5 int main()
 6 {
 7     while(scanf("%d%d",&n,&s)!=EOF)
 8     {
 9         F[n][s]=0;
10         for(int i=n;i>=0;i--)
11             for(int j=s;j>=0;j--)
12             {
13                 if(i==n && j==s) continue;
14                 F[i][j]=(i*(s-j)*F[i][j+1]+(n-i)*j*F[i+1][j]+(n-i)*(s-j)*F[i+1][j+1]+n*s)/(n*s-i*j);
15             }
16         printf("%.4f
",F[0][0]);
17     }
18     return 0;
19 }
C++

POJ 3744 矩阵乘法加速线性表达式递推。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int Maxn=20;
 6 struct Matrix {double a[3][3]; int x,y;};
 7 int n,a[Maxn];
 8 double p,Ans;
 9 inline Matrix operator * (Matrix A,Matrix B)
10 {
11     Matrix C; C.x=A.x,C.y=B.y;
12     memset(C.a,0,sizeof(C.a));
13     for (int i=1;i<=A.x;i++)
14         for (int j=1;j<=A.y;j++)
15             for (int k=1;k<=B.y;k++)
16                 C.a[i][j]+=A.a[i][k]*B.a[k][j];
17     return C;
18 }
19 inline Matrix Pow(Matrix x,int y)
20 {
21     
22     Matrix Ret; Ret.x=2,Ret.y=2;
23     memset(Ret.a,0,sizeof(Ret.a));
24     Ret.a[1][1]=Ret.a[2][2]=1;
25     
26     while (true)
27     {
28         if (y&1) Ret=Ret*x;
29         x=x*x; y>>=1;
30         if (y==0) break;
31     }
32     return Ret;
33 }
34 
35 double Get(int t)
36 {
37     if (t<=1) return 0;
38     if (t==2) return 1;
39     if (t==3) return p;
40     t-=3;
41     Matrix M; 
42     M.x=M.y=2;
43     M.a[1][1]=p;
44     M.a[1][2]=1-p;
45     M.a[2][1]=1;
46     M.a[2][2]=0;
47     M=Pow(M,t);
48     return M.a[1][1]*p+M.a[1][2];
49 }
50 
51 int main()
52 {
53     while (scanf("%d%lf",&n,&p)!=EOF)
54     {
55         for (int i=1;i<=n;i++) scanf("%d",&a[i]);
56         sort(a+1,a+n+1);
57         Ans=1;
58         for (int i=1;i<=n;i++)
59             Ans=Ans*Get(a[i]-a[i-1])*(1.0-p);
60         printf("%.7lf
",Ans);        
61     }
62     return 0;
63 }
C++

POJ 3071 直接DP即可

 1 #include <cstdio>
 2 #include <cstring>
 3 double F[10][250],p[250][250];
 4 int n,Ans;
 5 int main()
 6 {
 7     while (scanf("%d",&n)!=EOF)
 8     {
 9         if (n==-1) break;
10         memset(F,0,sizeof(F));
11         for (int i=1;i<=(1<<n);i++) 
12             for (int j=1;j<=(1<<n);j++) scanf("%lf",&p[i][j]);
13         for (int i=1;i<=(1<<n);i++) F[0][i]=1.0;
14         for (int i=1;i<=n;i++)
15             for (int j=1;j<=(1<<n);j++)
16                 for (int k=1;k<=(1<<n);k++)
17                     if (((j-1)>>(i-1)^1)==((k-1)>>i-1)) 
18                         F[i][j]+=F[i-1][j]*F[i-1][k]*p[j][k];
19         double Ret=0;
20         for (int i=1;i<=(1<<n);i++)    
21             if (F[n][i]>Ret) Ans=i,Ret=F[n][i];
22         printf("%d
",Ans);
23     }
24     return 0;
25 }
C++
原文地址:https://www.cnblogs.com/yyjxx2010xyu/p/5484111.html