hdu 4649 Professor Tian 反状态压缩+概率DP

思路:反状态压缩——把数据转换成20位的01来进行运算

因为只有20位,而且&,|,^都不会进位,那么一位一位地看,每一位不是0就是1,这样求出每一位是1的概率,再乘以该位的十进制数,累加,就得到了总体的期望。

对于每一位,状态转移方程如下:

f[i][j]表示该位取前i个数,运算得到j(0或1)的概率是多少。

f[i][1]=f[i-1][1]*p[i]+根据不同运算符和第i位的值运算得到1的概率。

f[i][0]=f[i-1][0]*p[i]+根据不同运算符和第i位的值运算得到0的概率。

初始状态:f[0][0~1]=0或1(根据第一个数的该位来设置)

每一位为1的期望 f[n][1]

这题只要知道怎样表示状态就很简单了!!!以上是标程……

代码如下:

 

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<algorithm>
 4 #include<iomanip>
 5 #include<cmath>
 6 #include<cstring>
 7 #include<vector>
 8 #define ll __int64
 9 #define pi acos(-1.0)
10 #define MAX 50000
11 using namespace std;
12 double dp[202][2],p[202];
13 char str[202];
14 int f[202];
15 double fun1(int i,int j){//位运算结果为1的期望值
16     double ans=0.0,pp=1-p[i];
17     int t=(f[i]>>j)&1;
18     if(str[i]=='&'&&t){
19         ans=dp[i-1][1]*pp;
20     }
21     else if(str[i]=='|'){
22         ans=dp[i-1][1]*pp;
23         if(t==1)
24             ans+=dp[i-1][0]*pp;
25     }
26     else if(str[i]=='^'){
27         if(t==1)
28             ans=dp[i-1][0]*pp;
29         else ans=dp[i-1][1]*pp;
30     }
31     return ans;
32 }
33 double fun0(int i,int j){//位运算结果为0的期望值
34     double ans=0.0,pp=1-p[i];
35     int t=(f[i]>>j)&1;
36     if(str[i]=='&'){
37         if(t==1)
38             ans=dp[i-1][0]*pp;
39         else ans=(dp[i-1][0]+dp[i-1][1])*pp;
40     }
41     else if(str[i]=='|'&&t==0)
42         ans=dp[i-1][0]*pp;
43     else if(str[i]=='^'){
44         if(t==1) ans=dp[i-1][1]*pp;
45         else ans=dp[i-1][0]*pp;
46     }
47     return ans;
48 }
49 int main(){
50     int c,n,i,j,k=0;
51     double ans;
52     while(scanf("%d",&n)!=EOF){
53         for(i=0;i<=n;i++) scanf("%d",&f[i]);
54         for(i=1;i<=n;i++) scanf("%s",&str[i]);
55         for(i=1;i<=n;i++) scanf("%lf",&p[i]);
56         ans=0.0;
57         for(i=0;i<20;i++){
58             c=(f[0]>>i)&1;
59             dp[0][1]=c; dp[0][0]=c^1;
60             for(j=1;j<=n;j++){
61                 dp[j][1]=dp[j-1][1]*(p[j])+fun1(j,i);
62                 dp[j][0]=dp[j-1][0]*(p[j])+fun0(j,i);
63             }
64             ans+=(1<<i)*dp[n][1];
65         }
66         printf("Case %d:\n%.6lf\n",++k,ans);
67     }
68     return 0;
69 }
View Code

 

 

posted @ 2013-08-09 20:15  _随心所欲_  阅读(300)  评论(0编辑  收藏  举报