(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
",f[la][0]);
return 0;
}