注意几点:
1.为什么要逆推?由此状态可以轻易算出彼状态是否可行,而彼状态却无法轻易还原为此状态。
2.为什么可以逆推?假设时光倒流了。。。。23333
3.注意位运算的准确,大胆写方程。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int k,n,p[],x,limit[];
double dp[][(<<)-];
int main()
{
scanf("%d%d",&k,&n);
for (int i=;i<=n;i++)
{
scanf("%d",&p[i]);
for (;;)
{
scanf("%d",&x);
if (!x) break;
limit[i]|=(<<(x-));
}
}
for (int i=k;i>=;i--)
{
for (int s=;s<=(<<n)-;s++)
{
dp[i][s]=;
for (int k=;k<=n;k++)
{
if ((s&limit[k])==limit[k])
dp[i][s]+=max(dp[i+][s],dp[i+][s|(<<(k-))]+p[k]);
else dp[i][s]+=dp[i+][s];
}
dp[i][s]/=n;
}
}
printf("%.6lf\n",dp[][]);
return ;
}