题意:
买零食凑卡片的游戏,浪费钱。
给出每包粮食含有某一张卡片的概率,当然也可能什么也没有。
问凑齐一套卡片的买的零食的数量的期望。
思路:
求期望,那么倒着dp。
因为n只有20,所以考虑用状态压缩来表示当前拥有的卡片的情况。
dp[sta]表示当前拥有卡片为sta时还需要买多少包零食,显然dp[(1<<n)-1] = 0。
dp[x] = Σdp[x|(1<<j)] * p[j],因为当前可能有些卡片已经有了,所以dp[x] = Σdp[x|(1<<j)] * p[j] + Σdp[x] * p[k],j为x表示中为0的点;
整理得到dp[x] = (Σdp[x|(1<<j)] * p[j]) / (Σp[j]),然后倒着dp即可。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 const int N = 21; 6 double dp[1<<N]; 7 double p[N]; 8 int main() 9 { 10 int n; 11 while (scanf("%d",&n) != EOF) 12 { 13 for (int i = 0;i < n;i++) scanf("%lf",&p[i]); 14 dp[(1<<n)-1] = 0; 15 for (int i = (1 << n) - 2;i >= 0;i--) 16 { 17 double tmp = 0; 18 for (int j = 0;j < n;j++) if (!(i&(1<<j))) tmp += p[j]; 19 double tt =0; 20 for (int j = 0;j < n;j++) 21 { 22 if (!(i&(1<<j))) 23 { 24 tt += dp[i|(1<<j)] * p[j]; 25 } 26 } 27 dp[i] = (tt + 1) / tmp; 28 } 29 printf("%.5f ",dp[0]); 30 } 31 return 0; 32 }