我数学期望还是太差了……
先考虑状压模型,设$dp[i][S]$表示第$i$轮,当前宝物状态为$S$,能获得的最大期望分数
然而这个模型有一个问题,第$i$轮不一定能达到状态$S$
那么考虑转化一下,$dp[i][S]$表示第$1$至$i-1$轮的宝物状态为$S$,第$i$至$n$轮的期望分数
那么我们就可以倒推了
那么对于第$k$个宝物,可以分为两种情况
1.可以选,那么此时可以选择选或者不选,则$dp[i][S]+=max{dp[i+1][S],dp[i+1][S|(1<<k-1)]+a[k]}$
2.不能选,那么$dp[i][S]+=dp[i+1][S]$
然后因为这玩意儿是一个期望,所以每一次做完之后都得$dp[i][S]/=n$
1 //minamoto 2 #include<cstdio> 3 #define max(a,b) ((a)>(b)?(a):(b)) 4 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 5 char buf[1<<21],*p1=buf,*p2=buf; 6 inline int read(){ 7 #define num ch-'0' 8 char ch;bool flag=0;int res; 9 while((ch=getc())>'9'||ch<'0') 10 (ch=='-')&&(flag=true); 11 for(res=num;(ch=getc())<='9'&&ch>='0';res=res*10+num); 12 (flag)&&(res=-res); 13 #undef num 14 return res; 15 } 16 const int N=105; 17 int n,m,sta[17],a[17],S;double dp[N][1<<15]; 18 int main(){ 19 // freopen("testdata.in","r",stdin); 20 m=read(),n=read(),S=1<<n; 21 for(int i=1,x;i<=n;++i){ 22 a[i]=read(); 23 while(x=read()) sta[i]|=1<<x-1; 24 } 25 for(int i=m;i;--i) 26 for(int j=0;j<S;++j){ 27 for(int k=1;k<=n;++k){ 28 if((j&sta[k])==sta[k]) dp[i][j]+=max(dp[i+1][j],dp[i+1][j|(1<<k-1)]+a[k]); 29 else dp[i][j]+=dp[i+1][j]; 30 } 31 dp[i][j]/=n; 32 } 33 printf("%.6lf ",dp[1][0]); 34 return 0; 35 }