解题思路:
若正着推,则一个状态会转移到两个状态,但我们不知道那一种更优,所以倒着推从两个状态转移到一个状态。
设 f[i][j] 表示从第i轮j这个状态开始可以得到的最高分,那么初始状态为 f[k+1][j]=0 ,我们要求的答案为 f[1][0] ,转移方程如下:
如果当前可以去第l个,则:
f[i][s]+=max(f[i+1][s],f[i+1][s|(1<<j−1)]+p[j])/n;
如果不行,则:
f[i][s]+=f[i+1][s]/n
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
if(c=='-')f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
int k,n,p[16],key[16];
double f[105][1<<15];
int main()
{
//freopen("lx.in","r",stdin);
k=getint(),n=getint();
for(int i=1,j;i<=n;i++)
{
p[i]=getint();
while(j=getint())
{
if(!j)break;
key[i]|=(1<<j-1);
}
}
for(int i=k;i;i--)
for(int s=0;s<(1<<n);s++)
for(int j=1;j<=n;j++)
{
if((key[j]&s)==key[j])
f[i][s]+=max(f[i+1][s],f[i+1][s|(1<<j-1)]+p[j])/n;
else
f[i][s]+=f[i+1][s]/n;
}
printf("%0.6f",f[1][0]);
}