BZOJ1076
来自蒟蒻XXJ的做题记录
倒着推一遍DP就OK
#include<bits/stdc++.h>
using namespace std;
const int MAXK=128;
const int MAXN=15;
inline int in(){
int a(0),f(1);char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') a=(a<<1)+(a<<3)+c-'0',c=getchar();
return a*f;
}
int k,n;
int s[MAXN],val[MAXN];
double kkk;
double dp[MAXK][(1<<15)];
void input(){
k=in();n=in();kkk=n;
for(int i=1;i<=n;i++){
val[i]=in();
int a;
while(1){
scanf("%d",&a);
if(!a) break;
s[i]|=(1<<(a-1));
}
}
}
void xxj(){
for(int i=k;i;--i)
for(int j=0;j<(1<<n);j++){
for(int kk=1;kk<=n;kk++){
//首先是下一个可以选择的情况
if((j&s[kk])==s[kk]) dp[i][j]+=max(dp[i+1][j],dp[i+1][j|(1<<(kk-1))]+val[kk]);
else dp[i][j]+=dp[i+1][j];
}
dp[i][j]/=kkk;
}
}
void output(){
cout<<fixed<<setprecision(6)<<dp[1][0]<<endl;
}
int main(){
input();
xxj();
output();
return 0;
}