http://acm.hdu.edu.cn/showproblem.php?pid=4649
2 1 2 3 ^ ^ 0.1 0.2 2 8 9 10 ^ ^ 0.5 0.78 1 1 2 & 0.5
Case 1: 0.720000 Case 2: 4.940000 Case 3: 0.500000
/** hdu4649 概率dp 题目大意:给定一个位运算服连接的表达式,第i个运算符与其后面的数字共同出现和消失,其消失的概率的为pi,问该表达式最后的期望值为多少 解题思路:由于为运算没有进位的影响,用dp[i][j][0~1]表示前j个数第i位0或1的期望为多少,那么最后dp[i][n][1]*(1<<i)加入最终结果就好了, 状态转移方程详见代码 */ #include <string.h> #include <iostream> #include <stdio.h> #include <algorithm> using namespace std; int n,a[1003]; double dp[25][500][2],p[500]; char s[1003][2]; int main() { int tt=0; while(~scanf("%d",&n)) { for(int i=0; i<=n; i++) { scanf("%d",&a[i]); } for(int i=1; i<=n; i++) { scanf("%s",s[i]); } for(int i=1; i<=n; i++) { scanf("%lf",&p[i]); } double ans=0; memset(dp,0,sizeof(dp)); for(int i=0; i<=20; i++) { if(a[0]&(1<<i))dp[i][0][1]=1; else dp[i][0][0]=1; for(int j=1; j<=n; j++) { ///第j个符号以及其后面的数字不考虑 dp[i][j][0]+=dp[i][j-1][0]*p[j]; dp[i][j][1]+=dp[i][j-1][1]*p[j]; ///第j个符号以及其后面的数字不考虑 if(a[j]&(1<<i))///第j个数的第i位为1 { if(s[j][0]=='&') { dp[i][j][1]+=dp[i][j-1][1]*(1-p[j]); dp[i][j][0]+=dp[i][j-1][0]*(1-p[j]); } else if(s[j][0]=='|') { dp[i][j][1]+=dp[i][j-1][0]*(1-p[j]); dp[i][j][1]+=dp[i][j-1][1]*(1-p[j]); } else { dp[i][j][1]+=dp[i][j-1][0]*(1-p[j]); dp[i][j][0]+=dp[i][j-1][1]*(1-p[j]); } } else///第j个数的第i位为0 { if(s[j][0]=='&') { dp[i][j][0]+=dp[i][j-1][1]*(1-p[j]); dp[i][j][0]+=dp[i][j-1][0]*(1-p[j]); } else if(s[j][0]=='|') { dp[i][j][0]+=dp[i][j-1][0]*(1-p[j]); dp[i][j][1]+=dp[i][j-1][1]*(1-p[j]); } else { dp[i][j][0]+=dp[i][j-1][0]*(1-p[j]); dp[i][j][1]+=dp[i][j-1][1]*(1-p[j]); } } } ans+=(1<<i)*dp[i][n][1]; } printf("Case %d:\n%.6lf\n",++tt,ans); } return 0; }