又是一道状态压缩,刚开始老是往博弈的方法想,总是没思路。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=21; const int inf=0x3f3f3f3f; int g,n,s; int sum[1<<N]; int res[10]; int c[22][10]; int dp[1<<N]; int main() { // freopen("in","r",stdin); while(scanf("%d%d%d",&g,&n,&s),g|n|s){ memset(c,0,sizeof c); for(int i=0;i<n;i++){ int k,x; scanf("%d",&k); while(k--){ scanf("%d",&x); c[i][x-1]++; } } int all=1<<n; for(int i=0;i<all;i++){ sum[i]=0; memset(res,0,sizeof res); for(int j=0;j<n;j++){ if(i&(1<<j)){ for(int k=0;k<g;k++)res[k]+=c[j][k]; } } for(int j=0;j<g;j++)sum[i]+=res[j]/s; } dp[0]=0; for(int i=1;i<all;i++){ dp[i]=-inf; for(int j=0;j<n;j++){ if(i&(1<<j)){ int pre=i^(1<<j); int now=(all-1)^pre; int tmp=sum[now]-sum[now^(1<<j)]; if(tmp)dp[i]=max(dp[i],dp[pre]+tmp); else dp[i]=max(dp[i],-dp[pre]); } } } printf("%d\n",dp[all-1]); } return 0; }