hdu 4336 Card Collector

题意:

买零食凑卡片的游戏,浪费钱。

给出每包粮食含有某一张卡片的概率,当然也可能什么也没有。

问凑齐一套卡片的买的零食的数量的期望。

思路:

求期望,那么倒着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 }
原文地址:https://www.cnblogs.com/kickit/p/9013357.html