题解:
状压dp+概率
f[i][j]表示正在扔第i次,已经有了j这些物品(状压),还可以拿多少价值
考虑当前抛第k个物品
当k的要求满足,f[i][j]+=1/n*max(f[i+1][j']+a[i],f[i+1][j])
当不满足,f[i][j]+=1/n*f[i+1][j]
其中j'=j|(1<<(k))(我是从0开始标号的)
代码:
#include<bits/stdc++.h> using namespace std; int p[105][1<<17],n,m,b[105]; double f[105][1<<16],a[105],P; double dfs(int x,int y) { if (x>m)return 0; if (p[x][y])return f[x][y]; p[x][y]=1; for (int i=0;i<n;i++) { if ((y&b[i])!=b[i])f[x][y]+=(P*dfs(x+1,y)); else f[x][y]+=max(P*dfs(x+1,y),P*(dfs(x+1,y|(1<<i))+a[i])); } return f[x][y]; } int main() { scanf("%d%d",&m,&n); P=1; P/=n; for (int i=0;i<n;i++) { scanf("%lf",&a[i]); int x; scanf("%d",&x); while (x) { b[i]+=(1<<(x-1)); scanf("%d",&x); } } printf("%.6lf",dfs(1,0)); }