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

 

 

你可能感兴趣的:(SSO)