Gems Fight!
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 327680/327680 K (Java/Others)
Total Submission(s): 2802 Accepted Submission(s): 1300
Problem Description
Alice and Bob are playing "Gems Fight!":
There are Gems of G different colors , packed in B bags. Each bag has several Gems. G different colors are numbered from color 1 to color G.
Alice and Bob take turns to pick one bag and collect all the Gems inside. A bag cannot be picked twice. The Gems collected are stored in a shared cooker.
After a player ,we name it as X, put Gems into the cooker, if there are S Gems which are the same color in the cooker, they will be melted into one Magic Stone. This reaction will go on and more than one Magic Stone may be produced, until no S Gems of the same color remained in that cooker. Then X owns those new Magic Stones. When X gets one or more new Magic Stones, he/she will also get a bonus turn. If X gets Magic Stone in a bonus turn, he will get another bonus turn. In short,a player may get multiple bonus turns continuously.
There will be B turns in total. The goal of "Gems Fight!" is to get as more Magic Stones than the opponent as possible.
Now Alice gets the first turn, and she wants to know, if both of them act the optimal way, what will be the difference between the number of her Magic Stones and the number of Bob's Magic Stones at the end of the game.
Input
There are several cases(<=20).
In each case, there are three integers at the first line: G, B, and S. Their meanings are mentioned above.
Then B lines follow. Each line describes a bag in the following format:
n c1 c2 ... cn
It means that there are n Gems in the bag and their colors are color c1,color c2...and color cn respectively.
0<=B<=21, 0<=G<=8, 0<n<=10, S < 20.
There may be extra blank lines between cases. You can get more information from the sample input.
The input ends with G = 0, B = 0 and S = 0.
Output
One line for each case: the amount of Alice's Magic stones minus the amount of Bob's Magic Stones.
Sample Input
3 4 3 2 2 3 2 1 3 2 1 2 3 2 3 1 3 2 2 3 2 3 1 3 1 2 3 0 0 0
Sample Output
3 -3
Hint
For the first case, in turn 2, bob has to choose at least one bag, so that Alice will make a Magic Stone at the end of turn 3, thus get turn 4 and get all the three Magic Stones.
Source
2013 Asia Hangzhou Regional Contest
题意:现在有一些宝石,这些宝石有G种颜色,有B个袋子,这些宝石装在袋子里,给出每个袋子里每种颜色宝石的数量,现在进行一个游戏。
游戏规则:两个人轮流操作,每次操作选一个袋子,将其中的宝石全部放进一个容器里面,如果容器中某种颜色的宝石的个数达到s,操作者获得(num/s)个魔力宝石,剩下的宝石不会消失,如果某个回合得到的魔力宝石的数量大于0(至少有一个)这个人可以获得一个新的回合(条件允许可以一直操作到所有宝石消耗完毕)。
问题:两个人都采用最优策略,求(先手得到的魔力宝石数量-后手得到的魔力宝石数量),该值可以为负。
分析: 0<=B<=21, 0<=G<=8, 0<n<=10, S < 20。 由于B<=21,可以想到对袋子进行状态压缩,0表示袋子已经被取走,1表示未被取走。由于每个宝石的数量是给定的,最后所有袋子一定会被全部取完,那么先手和后手所得到的魔力宝石的数组总量是一定的。用dp[st]表示从st状态开始,先手能获得的最大魔力宝石数量。
设temp为选第i个袋子后能获得的魔力宝石数量
当temp>0时,可以连续行动,dp[st]=max(dp[st-(1<<i)]+temp)
当temp=0时,下个回合时对手行动,dp[st]=max(未选取袋子能生成的魔力宝石数量-dp[st-(1<<i)])
例:st=010010 st-(1<<i)=010000;
temp大于0时,说明从010010状态下,取走第i个袋子,可以连续行动,那么dp[010010]=dp[010000]+temp
temp小于0时,说明从010010状态下,取走第i个袋子,不能连续行动,那么要求从010010状态先手的情况,010000状态下的先手就变成了后手,dp[010010]=left(未选取袋子能生成的魔力宝石数量)-dp[010000] 。
最后求差,用2*ans-sum即可。
#include"bits/stdc++.h"
using namespace std;
const int inf = -(1<<30);
int g,b,s,n;
int dp[1<<22];
int color[10];
int bag[30][10];
int dfs(int st,int left,int c[])
{
if(left==0||st==0)return 0;
if(dp[st]!=inf)return dp[st];
int ans=0;
for(int i=1;i<=b;i++)
{
int cnt=0;
int x=1<<i;
if(!(st&x))continue;
int temp=0;
int cc[10];//储存容器里面剩下的宝石
for(int j=1;j<=g;j++)
{
temp+=(c[j]+bag[i][j])/s;
cc[j]=(c[j]+bag[i][j])%s;
}
if(temp)
{
ans=max(ans,temp+dfs(st-x,left-temp,cc));
}
else ans=max(ans,left-dfs(st-x,left-temp,cc));
}
dp[st]=ans;
return ans;
}
int main()
{
while(~scanf("%d%d%d",&g,&b,&s)&&g)
{
for(int i=0;i<=1<<(b+1);i++)dp[i]=inf;
memset(color,0,sizeof(color));
memset(bag,0,sizeof(bag));
for(int i=1;i<=b;i++)
{
scanf("%d",&n);
int x;
while (n--)
{
scanf("%d",&x);
color[x]++;
bag[i][x]++;
}
}
int sum=0;
for(int i=1;i<=g;i++) sum+=color[i]/s;
int f[10];
memset(f,0,sizeof(f));
int ans=dfs((1<<(b+1))-1,sum,f);
printf("%d\n",ans*2-sum);
}
}