期望dp小结
来源:互联网 发布:淘宝刷销量好评 编辑:程序博客网 时间:2024/06/05 13:26
前言:期望dp状态的定义是较为显然的,但对于状态的转移往往需要一些公式的推导。关键的几点是状态之间的互通性,和状态转移的花费,以及转移的概率
解决期望dp的几个技巧如下:
一.利用期望的线性性质:
我们所求的期望可以化为多个步骤的期望累和
相关题目:J,L
二.采用逆序的方式:
在目标确定的情况下,可以得知在目标到达目标的期望值为0,然后根据期望的线性性质怎么又是线性性质 得到状态转移方程:
dp[i]+=(dp[j]+cost)*p cost是转移的花费 p是概率 有时要除以(1-转移到自己的概率,但这是又不能单纯地+cost)所以要结合具体情况考虑
相关题目:A,C,D,E
三.利用期望的定义求解:
E[A]=a1*p1+a2*p2+…+an*pn;
a1,a2…an为各种方案(情况)的花费(权值),p1,p2…pn为对应方案(情况)的发生概率 所以在最终方案确定且较少时,只用计算出发生的概率,在最后再乘上权值求累和就好了
相关题目:G,J
实际上,更多的题目需要自己推出公式,并按照推出的规律进行一些状态转移
像这种题,难度就会略高一些:
相关题目:B,H,I
题目选讲:
B:参见Komachi dalao博客
G:
看到
但如果单纯地算每个数被计算出的概率,那么复杂度为稳定吃Tle
题目的另外一个特别之处在于:只有|,&,^三个运算符,他们在运算时是不会发生进位的,所以可以直接记录每一位数出现0或1的概率,然后在最后直接概率乘上权值就好了
参见代码:
#include<cstdio>double dp[205][25][2],P[205];int A[205];int B[205][25];char op[205][3];int main(){ int n,cnt=0; while(~scanf("%d",&n)){ cnt++; for(int i=1;i<=n+1;i++) scanf("%d",&A[i]); for(int i=1;i<=n;i++)scanf("%s",op[i]); for(int i=1;i<=n;i++)scanf("%lf",&P[i]); for(int i=0;i<=20;i++)for(int j=0;j<=n;j++)for(int k=0;k<2;k++)dp[j][i][k]=0; for(int k=1;k<=n+1;k++) for(int i=0;i<=20;i++) if(A[k]&(1<<i))B[k][i]=1; else B[k][i]=0; for(int i=0;i<=20;i++) if(B[1][i])dp[0][i][1]=1; else dp[0][i][0]=1; for(int i=1;i<=n;i++){ for(int j=0;j<=20;j++){ double p=1-P[i]; if(op[i][0]=='&'){ if(B[i+1][j]==0)dp[i][j][0]+=(dp[i-1][j][0]+dp[i-1][j][1])*p; else { dp[i][j][1]+=dp[i-1][j][1]*p; dp[i][j][0]+=dp[i-1][j][0]*p; } } else if(op[i][0]=='|'){ if(B[i+1][j]==0){ dp[i][j][0]+=dp[i-1][j][0]*p; dp[i][j][1]+=dp[i-1][j][1]*p; } else dp[i][j][1]+=(dp[i-1][j][1]+dp[i-1][j][0])*p; } else if(op[i][0]=='^'){ if(B[i+1][j]==0){ dp[i][j][0]+=dp[i-1][j][0]*p; dp[i][j][1]+=dp[i-1][j][1]*p; } else { dp[i][j][0]+=dp[i-1][j][1]*p; dp[i][j][1]+=dp[i-1][j][0]*p; } } dp[i][j][1]+=dp[i-1][j][1]*P[i]; dp[i][j][0]+=dp[i-1][j][0]*P[i]; } } double ans=0; for(int j=0;j<=20;j++) ans+=dp[n][j][1]*(1<<j); printf("Case %d:\n%.6f\n",cnt,ans); } return 0;}
J:
可以知道,对于m道题的每n道题,会对应不同的n个人
那么可以直接对这n个人对应n道题进行状压dp,复杂度
根据期望的线性性质,我们可以把每个阶段的期望值都加起来,然后就可以得到答案
#include<cstdio>double dp[15][1200];double P[15][1005];template <class _> _ max(_ x,_ y){return x>y?x:y;}template <class _> _ min(_ x,_ y){return x<y?x:y;}int main(){ int T,t=0; scanf("%d",&T); while(T--){ int n,m; scanf("%d %d",&n,&m); for(int i=0;i<n;i++) for(int j=1;j<=m;j++) scanf("%lf",&P[i][j]); double ans=0; int cnt=(m-1)/n+1,tta=(1<<n)-1; for(int k=0;k<cnt;k++){ int len=min(m,k*n+n); len-=k*n; for(int i=0;i<=len;i++)for(int j=0;j<=tta;j++)dp[i][j]=-1; dp[0][0]=0; for(int i=1;i<=len;i++){//k*n+i for(int j=0;j<=tta;j++){ if(dp[i-1][j]==-1)continue; for(int h=0;h<n;h++){ if((j&(1<<h)))continue; dp[i][j|(1<<h)]=max(dp[i][j|(1<<h)],dp[i-1][j]+P[h][k*n+i]); } } } double sum=0; for(int i=0;i<=tta;i++) if(dp[len][i]>sum)sum=dp[len][i]; ans+=sum; } printf("Case #%d: %.5f\n",++t,ans); } return 0;}
L:
仍是根据期望的线性性质,求被覆盖点的期望,可以化简为求所有点被覆盖的期望的累和。然后利用容斥,算出点不被覆盖的概率p,然后
#include<cstdio>int main(){ int T,t=0; scanf("%d",&T); while(T--){ int n,m,k; scanf("%d%d%d",&n,&m,&k); long long tmp=1ll*n*n*m*m; double ans=0; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ long long s=0; s+=1ll*n*n*(j-1)*(j-1); s+=1ll*m*m*(i-1)*(i-1); s+=1ll*n*n*(m-j)*(m-j); s+=1ll*m*m*(n-i)*(n-i); s-=1ll*(i-1)*(i-1)*(j-1)*(j-1); s-=1ll*(i-1)*(i-1)*(m-j)*(m-j); s-=1ll*(n-i)*(n-i)*(m-j)*(m-j); s-=1ll*(n-i)*(n-i)*(j-1)*(j-1); double p=1.0*s/tmp; double d=1; for(int h=1;h<=k;h++)d=d*p; ans+=1-d; } } printf("Case #%d: %.f\n",++t,ans); } return 0;}
- 数学期望DP小结
- 期望dp小结
- 期望dp小结
- DP期望
- 期望DP
- 期望DP
- 期望dp
- 期望DP
- ZJU3582 期望DP
- 概率dp 求期望
- zoj3329(期望DP)
- hdu-4405(dp+期望)
- hdu 4336 期望dp
- zoj3329(期望DP)
- uva 11600(期望dp)
- hdoj 5045 期望dp
- HDU 4405 期望DP
- POJ 2096 期望DP
- 图的基本概念
- 718. Maximum Length of Repeated Subarray
- KMP算法详解
- [USACO09OPEN]滑雪课Ski Lessons
- CT重建学习笔记(一)
- 期望dp小结
- oracle创建表空间,用户及授权
- 云片短信验证
- 生活小记37
- Oracle数据库中插入日期,日期带有时分秒(java.util.Date类型)
- 20171031分包班组宝动作
- 浅谈TCP/IP模型
- 用C语言操作MySQL数据库
- Redis设计与实现——数据结构(三)