传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4778
题目大意:有B个包裹,里面有各种颜色的GEM,共有G个颜色。Alice和Bob轮流挑选包裹放到一个地方,如果挑选出来的同种颜色的GEM超过S个,当前回合者可以得分,每超过S个得一分。如果在回合内得分了,可以额外进行一个回合。问Alice的得分减去Bob的得分最大是多少。
分析:很明显的极大极小。基本上可以说和POJ1085一样的,记忆化搜索 + 状态压缩
代码:
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cassert>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <list>
#include <stdexcept>
#include <functional>
#include <utility>
#include <ctime>
using namespace std;
/** some operate*/
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define foreach(e,x) for(__typeof(x.begin()) e=x.begin();e!=x.end();++e)
#define CLR(arr) memset(arr,0,sizeof(arr))
/** some const*/
#define N 300010
#define PI acos(-1.0)
#define oo 1000000000
#define loo 1000000000000000000LL
/** some alias*/
typedef long long ll;
typedef double db;
int dx[]={0,-1,0,1, -1,-1,1,1};
int dy[]={1,0,-1,0, -1,1,-1,1};
/** Global variables*/
struct node
{
int c[10];
}Bag[30];
int b,g,s,now[10],sg[1<<22];
int judge(int k)
{
int temp,total = 0;
REP(i,g+1)
{
temp = now[i] + Bag[k].c[i];
if(temp >= s)
total += temp / s;
}
return total;
}
int dfs(int dp)
{
if(sg[dp] != -oo)
return sg[dp];
int tep[10],ans = -oo;
REP(i,g+1)
tep[i] = now[i];
REP(i,b)
{
int k = 1 << i;
if(!(dp & k))
{
int total = judge(i);
REP(j,g+1)
now[j] = (now[j] + Bag[i].c[j] ) % s;
if(total > 0)
ans = max(ans,total + dfs(dp|k));
else
ans = max(ans,total - dfs(dp|k));
REP(j,g+1)
now[j] = tep[j];
}
}
return sg[dp] = ans;
}
void init()
{
int k = 1 << b;
REP(i,k)
sg[i] = -oo;
sg[k-1] = 0;
}
int main()
{
//freopen("a","r",stdin);
//freopen("wa","w",stdout);
int n,m,t,cs=0;
while(~scanf("%d%d%d",&g,&b,&s))
{
if(!b && !g && !s)
break;
init();
CLR(now);
CLR(Bag);
REP(i,b)
{
scanf("%d",&n);
while(n--)
{
scanf("%d",&m);
Bag[i].c[m]++;
}
}
printf("%d\n",dfs(0));
}
return 0;
}