题意:买泡面,得水浒传n张英雄卡,每张卡有一个得到的概率,问购买次数的期望,能集齐所有卡
思路:概率dp+状态压缩,dp[s]表示搜集到的卡片状态的期望次数,1表示有的,0表示没有,那么dp[s] = (1 - sum(p[i])) * dp[s] + p[k] * dp[s] + p[j] * dp[s|(1<<j)] + 1,其中i为所有英雄,k为已经搜集到的英雄,j为还未搜集到的英雄,移项得,dp[s] = (sum(p[j] * dp[s|(1<<j)]) + 1) / sum[p[j]];
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 25;
int n;
double p[N], dp[(1<<20) + 5];
int main() {
while (~scanf("%d", &n)) {
for (int i = 0; i < n; i++) scanf("%lf", &p[i]);
int maxs = (1<<n) - 1;
for (int i = maxs - 1; i >= 0; i--) {
dp[i] = 1;
double sum = 0;
for (int j = 0; j < n; j++) {
if (!(i&(1<<j))) {
dp[i] += p[j] * (dp[i|(1<<j)]);
sum += p[j];
}
}
dp[i] /= sum;
}
printf("%.4lf\n", dp[0]);
}
return 0;
}