luogu P2473 [SCOI2008]奖励关
\(n\)很小,可以想到设\(f_{i,j}\)为第\(i\)轮,获得的物品集合为\(j\)的答案,然后顺推
恭喜你很可能会WA,因为这样可能会有些状态无法到达,而难以计算答案
概率期望是可以逆推的,那么\(f_{i,j}\)为第\(i\)轮及之前获得的物品集合为\(j\),\(i\)后面的最大期望得分,转移就枚举每个物品能不能放,以及如果能放会不会放(后者要取max)
最后答案为\(f_{1,0}\)
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define db double
#define s(i) (1<<(i-1))
using namespace std;
const int N=16,M=(1<<15)+10;
il LL rd()
{
re LL x=0,w=1;re char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int kk,n,nn,a[N][2];
db f[2][M],inf;
int main()
{
kk=rd(),n=rd(),nn=1<<n;
for(int i=1;i<=n;i++)
{
a[i][0]=rd();
while(1)
{
int x=rd();
if(!x) break;
a[i][1]|=s(x);
}
}
int nw=1,la=0;
for(int h=kk;h>=1;h--)
{
for(int i=0;i<nn;i++)
{
f[nw][i]=0;
for(int j=1;j<=n;j++)
if((i&a[j][1])==a[j][1]) f[nw][i]+=max(f[la][i|s(j)]+(db)a[j][0],f[la][i])/(db)n;
else f[nw][i]+=f[la][i]/(db)n;
}
nw^=1,la^=1;
}
printf("%.6lf\n",f[la][0]);
return 0;
}