测试地址:Card Collector
题目大意:要收集
n(n≤20)
张不同的卡片,每一次有
pi
的概率得到第
i
张卡片,每次最多获得一张卡片,有可能一张卡片都得不到,求收集完所有卡片所需要的期望次数。
做法:本题需要用到状态压缩DP和期望DP。
首先,我们发现
f(state)=(∑next为state的后继状态pnext×f(next))+1
其中后继状态指
state
可能转移到的状态,
pnext
则为转移到这个状态的概率。转移后的状态可能是多获得了某张卡片,也可能是得到了已有的卡片或者没得到卡片(这时
next=state
)。由于左边和右边都有
f(state)
,因此要移项之后再求出
f(state)
。这样最后的答案就是
f(0)
了,总的时间复杂度为
O(n2n)
,可以通过此题。
以下是本人代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n;
double p[25],f[2000010];
bool vis[2000010];
double dp(int x)
{
if (vis[x]) return f[x];
if (x==(1<<n)-1) return 0;
f[x]=0;
double P=0.0;
for(int i=1;i<=n;i++)
if (!(x&(1<<(i-1))))
{
P+=p[i];
f[x]+=p[i]*dp(x+(1<<(i-1)));
}
f[x]=(f[x]+1)/P;
vis[x]=1;
return f[x];
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
scanf("%lf",&p[i]);
printf("%lf\n",dp(0));
}
return 0;
}