3
5
2016
0

[BZOJ1076] [SCOI2008]奖励关

状态压缩DP

根据期望的线性性,我们知道可以分开考虑每个物品在每一时刻出现的期望

然后把这些期望加起来再除以物品种类数(因为要求平均期望,而每种物品出现的概率都是1/k)

那么DP方程就是

f[i][j]+=max(f[i+1][j],f[i+1][j|bit[k]]+score[k]);(其中满足可以取k物品的条件)

f[i][j]+=f[i+1][j];(当前枚举到的k物品没办法取到所得到的上一次的平均得分期望)

最后f[i][j]/=k就可以了

为什么要从f[i+1][j]推导f[i][j]?因为如果顺推的话有可能会枚举到无效的状态,而且最后没办法输出f[n][j]

所以只需要倒推就可以解决问题啦

#include<cstdio>
#include<algorithm>
using namespace std;

int k,n,bit[25],ist[25],score[25];
double f[105][1<<15];

int main(){
freopen("1076.in","r",stdin);
freopen("1076.out","w",stdout);
scanf("%d %d",&n,&k);
for(int i=1;i<=20;i++)bit[i]=1<<(i-1);
for(int i=1;i<=k;i++){
	scanf("%d",&score[i]);
	int tp;
	for(int j=0;scanf("%d",&tp),tp;j++){
		ist[i]|=bit[tp];
	}
}
for(int i=n;i>=1;i--){
	for(int j=0;j<=bit[k+1]-1;j++){
		for(int l=1;l<=k;l++){
			if((j&ist[l])==ist[l]){
				f[i][j]+=max(f[i+1][j],f[i+1][j|bit[l]]+score[l]);
			}
			else f[i][j]+=f[i+1][j];
		}
		f[i][j]/=k;
	}
}
printf("%.6f\n",f[1][0]);
return 0;
}
Category: BZOJ | Tags: OI bzoj | Read Count: 640

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com