zoukankan      html  css  js  c++  java
  • 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:
    %.6lf
    ",++k,ans);
    67     }
    68     return 0;
    69 }
    View Code

  • 相关阅读:
    windows环境变量
    软件工程的一般过程和需要的文档
    linux find 命令查找文件和文件夹
    mybatis中mapUnderscoreToCamelCase自动驼峰命名转换
    人体湿气重有哪些表现? 细数湿气重的危害
    MySQL升级后1728错误解决方案
    linux清理Java环境
    无线投屏PC投电视
    report studio 交叉表占比
    Cognos审核模块的导入与设置
  • 原文地址:https://www.cnblogs.com/xin-hua/p/3248975.html
Copyright © 2011-2022 走看看