您的位置:首页 > 其它

BZOJ 1076: [SCOI2008]奖励关 [DP 期望 状压]

2017-03-05 16:26 495 查看
传送门

题意:$n$种宝物,出现$k$次每次一种,每种宝物有价值和吃掉它之前必须要吃掉的宝物的集合,求采取最优策略的期望最大价值

1<=k<=100,1<=n<=15,分值为[-10^6,10^6]内的整数。

看到$n$应该想到状压....

$f[i][s]$表示前$i$次已经吃掉的集合为$s$的期望最大值

然而正推的话,答案是谁呢?

所以倒推,表示这个状态到结束得到的期望最大值

转移枚举出现的宝物,最后乘上概率$\frac{1}{n}$

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=105,S=1<<15;
inline int read(){
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
int m,n,val
,need
;
double f
[S];
int main(){
freopen("in","r",stdin);
m=read();n=read();
for(int i=0;i<n;i++){
val[i]=read();int x=read();
while(x) need[i]|=(1<<(x-1)),x=read();
}
int All=1<<n;
for(int i=m;i>=1;i--)
for(int s=0;s<All;s++){
for(int j=0;j<n;j++){
if((s&need[j])==need[j]) f[i][s]+=max(f[i+1][s],f[i+1][s|(1<<j)]+val[j]);
else f[i][s]+=f[i+1][s];
}
f[i][s]/=n;
}
printf("%.6lf",f[1][0]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: