用状态压缩来表示当前已经取的卡片,关键在于dp[i]的转移,dp[i]是由某个状态取一张牌转移过来的,所以考虑状态。
可能由没有卡的包和没有起作用的牌转移过来(i里面二进制为0的位置),也可能是i里面的1由0变成1的。
所以方程可以写成:dp[i]=(s1+s2)*dp[i]+sigma(dp[i^(1<<j)]*a[j])+1,其中s2是i为0处概率的和.
代码如下:
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#define rep(a,b,i) for(i=a;i<=b;i++)
using namespace std;
double dp[1<<20];
double a[21];
int main()
{
int i,j,n,p;
double s1,s2,s3;
while(cin>>n){
p=1<<n;
memset(dp,0,sizeof(dp));
s3=0;
for(i=0;i<n;i++){
scanf("%lf",&a[i]);
s3+=a[i];
}
s3=1-s3;
for(i=1;i<p;i++){
s1=0;
s2=0;
for(j=0;j<n;j++){
if(i&(1<<j)){
s1+=dp[i^(1<<j)]*a[j];
}
if(!(i&(1<<j)))
s2+=a[j];
}
s2+=s3;
dp[i]=(s1+1)/(1-s2);
}
printf("%.4lf\n",dp[p-1]);
}
}