bzoj1076: [SCOI2008]奖励关
状态压缩dp。
一道很好的dp题。
我们在选的时候并不知道它会对后面的选择造成什么影响,所以不能正向dp。
f[i][s]表示第i次选择后,选择的宝物二进制为s的期望得分。
初始状态均为0,答案为f[0][0]。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 20; const int maxm = 1<<16; const int maxk = 100 + 10; int n,m,k; int pre[maxn]; int p[maxn]; double f[maxk][maxm]; int main() { scanf("%d%d",&k,&n); m=(1<<n)-1; for(int i=1,t;i<=n;i++) { scanf("%d",&p[i]); while(scanf("%d",&t) && t) pre[i]|=1<<(t-1); } for(int i=k-1;i>=0;i--) { for(int s=0;s<=m;s++) { for(int j=1;j<=n;j++) if((s&pre[j])==pre[j]) f[i][s]+=max(f[i+1][s],f[i+1][s|(1<<(j-1))]+p[j]); else f[i][s]+=f[i+1][s]; f[i][s]/=n; } } printf("%.6lf\n",f[0][0]); return 0; }