您的位置:首页 > 其它

【BZOJ】1076 [SCOI2008]奖励关 期望DP+状压DP

2018-03-06 22:10 295 查看

【题意】n种宝物,k关游戏,每关游戏给出一种宝物,可捡可不捡。每种宝物有一个价值(有负数)。每个宝物有前提宝物列表,必须在前面的关卡取得列表宝物才能捡起这个宝物,求期望收益。k<=100,n<=15。

【算法】期望DP+状压DP

【题解】主要需要记录的状态是前缀已有宝物,所以设f[i][S]表示前i关已有宝物列表S的期望收益。

根据全期望公式,依赖于第i+1关的宝物选择:(如果列表符合)

$$f[i][S]=\sum_{i=1}^{n}\frac{1}{n}*Max(f[i+1][S'],f[i+1][S])\ \ ,\ \ S'=S|(1<<(i-1))$$

倒推是因为已知前缀列表S的情况下,很容易判断下一关宝物是否可捡。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int inf=100000;
int a[20],n,m,v[20];
double f[200][70000];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&v[i]);
int u;scanf("%d",&u);
a[i]=0;
while(u!=0)
{
a[i]|=(1<<(u-1));
scanf("%d",&u);
}
}
int maxe=(1<<m)-1;
for(int i=n-1;i>=0;i--)
{
for(int j=0;j<=maxe;j++)
{
f[i][j]=0;
for(int k=1;k<=m;k++)
{
if((a[k]&j)==a[k])f[i][j]+=max(f[i+1][j],f[i+1][j|(1<<(k-1))]+v[k]);
else f[i][j]+=f[i+1][j];
}
f[i][j]/=m;
}
}
printf("%.6lf",f[0][0]);
return 0;
}
View Code

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: