HDU 4778 Gems Fight!

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 4778 Gems Fight!相关的知识,希望对你有一定的参考价值。

Gems Fight!

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

 
题意:Alice和Bob又在玩游戏啦(真是服了这两个人,天天玩各种各样的游戏)!游戏是Alice先手的,两人轮流操作,每次操作可以任选一个袋子,将里面的所有宝石扔进熔炉。给出正整数G,B,S,分别代表宝石总共有G种颜色,有B个袋子,当熔炉中有一种颜色的宝石超过S个时,当前进行操作的人可以得到魔法石,并且得到魔法石的人可以奖励连续操作。现在两人都用最佳策略玩,问最后先手减去后手的魔法石个数为多少。
 
题解:看看数据范围比较小,要么用搜索,要么用状压DP。
很显然,这题搜索是要TLE的。那么我们选择状压DP。
首先我们要明确一点:两人玩游戏都是用最佳策略。对于面对一个局面,我们无需考虑这个局面从何而来,只需考虑怎样走让当前玩家获得的魔法石数量达到最大。所以该题很明显是博弈思想。
既然如此,我们可以使用逆推法来解决此题。
我们要从最终状态,即所有袋子都被使用过的状态开始向后推导,直到所有袋子都没有被使用,我们就可以知道Alice面对的最佳状态了。
因此我们用f[i]表示在i这个状态,先手减后手的魔法石数量。(其中二进制为0表示袋子已被使用,1表示袋子未被使用)
根据f[i]的定义,我们就赋初值f[0]=0,然后向后推导。
对于二进制位为0的袋子,我们先把所有不同颜色的宝石取来对S取模,表示熔炉里还剩下了哪些颜色的宝石的个数。之所以对S取模是因为一旦超过S是需要做魔法石的。两人用最优策略玩肯定不会出现有一种颜色宝石数量在熔炉里≥S。因此,先这样处理出i状态下的熔炉情况。
然后对于二进制位为1的袋子,我们一个一个取,分开操作(因为在没有奖励的情况下,两人只能轮流取一个袋子),看看是否能使自己获得魔法石。如果不能,则说明此操作给对方加上了贡献,所以f[i]=max(f[i],-f[i^(1<<j)]);如果获得了魔法石,则说明此操作给自己加上了贡献,则f[i]=max(f[i],cnt+f[1^(1<<j)])。
最后f[(1<<B)-1],即Alice面对最初情况能获得的最优解,输出即可。
技术分享
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=25,M=10;
 4 int G,B,S,n,x,a[N],b[N],c[N][M],f[(1<<21)+5];
 5 int main()
 6 {
 7     while ((scanf("%d%d%d",&G,&B,&S))&&(G+B+S))
 8     {
 9         memset(c,0,sizeof(c));
10         for (int i=0;i<B;++i)
11         {
12             scanf("%d",&n);
13             for (int j=1;j<=n;++j)
14             {
15                 scanf("%d",&x);
16                 ++c[i][x];
17             }
18         }
19         f[0]=0;
20         for (int i=1;i<(1<<B);++i)
21         {
22             f[i]=-1e9;
23             memset(a,0,sizeof(a));
24             for (int j=0;j<B;++j)
25             if ((i&(1<<j))==0)
26             {
27                 for (int k=1;k<=G;++k)
28                 a[k]+=c[j][k],a[k]%=S;
29             }
30             for (int j=0;j<B;++j)
31             if (i&(1<<j))
32             {
33                 for (int k=1;k<=G;++k) b[k]=a[k];
34                 int cnt=0;
35                 for (int k=1;k<=G;++k)
36                 b[k]+=c[j][k],cnt+=b[k]/S,b[k]%=S;
37                 if (cnt) f[i]=max(f[i],cnt+f[i^(1<<j)]);
38                 else f[i]=max(f[i],-f[i^(1<<j)]);
39             }
40         }
41         printf("%d\n",f[(1<<B)-1]);
42     }
43     return 0;
44 }
View Code

 















以上是关于HDU 4778 Gems Fight!的主要内容,如果未能解决你的问题,请参考以下文章

hdu4778状态压缩

(dp)HDU6199- gems gems gems

按比例空间定位对象

java http://code-fight.club/fight/43/ternary-operator-vs-if-else-when-initialize-

Fight for myself

fight