[HDU 4336] Card Collector (状态压缩概率dp)

时间:2023-03-08 17:42:39

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4336

题目大意:有n种卡片,需要吃零食收集,打开零食,出现第i种卡片的概率是p[i],也有可能不出现卡片。问你收集齐n种卡片,吃的期望零食数是多少?

状态压缩:f[mask],代表收集齐了mask,还需要吃的期望零食数。

打开包装,有3种情况,第一种:没有卡片,概率(1-sigma(p[i]))

第二种,在已知种类中:概率sigma(p[j])

第三种,在未知种类中:p[k]

因此 f[mask] = f[mask]*(1-sigma(p[i])) + f[mask] * sigma(p[j]) + sigma(f[mask|k]*p[k]) + 1

 ///#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <bitset>
#include <cmath>
#include <numeric>
#include <iterator>
#include <iostream>
#include <cstdlib>
#include <functional>
#include <queue>
#include <stack>
#include <string>
#include <cctype>
using namespace std;
#define PB push_back
#define MP make_pair
#define SZ size()
#define ST begin()
#define ED end()
#define CLR clear()
#define ZERO(x) memset((x),0,sizeof(x))
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
const double EPS = 1e-; const int MAX_N = ;
int N;
double p[MAX_N+],f[<<MAX_N]; int main(){ while( ~scanf("%d",&N) ) {
ZERO(f);
double sum = 0.0;
for(int i=;i<=N;i++){
scanf("%lf",&p[i]);
sum += p[i];
}
f[(<<N)-] = ;
for( int mask=(<<N)-;mask>=;mask-- ){
double p1 = ;
for(int i=;i<N;i++){
if( (mask>>i)& ) {
p1 += p[i+];
}
}
// printf("p1 = %f\n",p1);
double p2 = ;
for(int i=;i<N;i++){
if( !((mask>>i)&) ) {
p2 += f[mask|(<<i)]*p[i+];
// printf("f[mask|(1<<i)]=%f\n",f[mask|(1<<i)]);
}
}
// printf("p2 = %f\n",p2);
f[mask] = (p2+1.0)/(sum-p1);
}
printf("%.10f\n",f[]);
} return ;
}