用f[i][j]表示到第i轮,之前取过的状态为j时之后的期望收益,枚举第i轮出现的物品,并判断能否取来转移,最终再将f[i][j]/=n即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m,x,a[105],b[105]; 4 double f[105][100005]; 5 int main(){ 6 scanf("%d%d",&m,&n); 7 for(int i=0;i<n;i++){ 8 scanf("%d",&a[i]); 9 while (scanf("%d",&x)!=EOF){ 10 if (!x)break; 11 b[i]|=(1<<x-1); 12 } 13 } 14 for(int i=m;i;i--) 15 for(int j=0;j<(1<<n);j++){ 16 for(int k=0;k<n;k++) 17 if ((j&b[k])!=b[k])f[i][j]+=f[i+1][j]; 18 else f[i][j]+=max(f[i+1][j],f[i+1][j|(1<<k)]+a[k]); 19 f[i][j]/=n; 20 } 21 printf("%.6f",f[1][0]); 22 }