(状压dp)HDU 4778 Gems Fight!

Gems Fight!

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others)
Total Submission(s): 2395    Accepted Submission(s): 1087

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

用dp[st]表示状态st下,用余下的未选的包裹能对当前先手做出的最大贡献。(即使当下的先手最大化其最终个数与对手的个数的差值)。末状态时显然贡献为0(双方均无包裹可再取)。而最初的的dp值显然需要由其产生的各种状况综合比较得到,故我们考虑逆向dp。每次先求出当前状态各种g余下的个数,对于下一个状况,统计加上后g的个数,设所有新的g共可以生成cnt个魔法石,如果cnt>0,则下一个状况的先手存在就是当下状况先手的可能,故用cnt+dp[st_new]更新,不然必改变了先手,用cnt-dp[st_new]更新。

 1 #include <iostream>
 2 #include <string>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <queue>
 8 #include <set>
 9 #include <map>
10 #include <list>
11 #include <vector>
12 #include <stack>
13 #define mp make_pair
14 //#define P make_pair
15 #define MIN(a,b) (a>b?b:a)
16 //#define MAX(a,b) (a>b?a:b)
17 typedef long long ll;
18 typedef unsigned long long ull;
19 const int MAX=40;
20 const int INF=1e9+5;
21 using namespace std;
22 //const int MOD=1e9+7;
23 typedef pair<ll,int> pii;
24 const double eps=0.00000001;
25 int dp[1<<21];
26 int num[30][10];
27 int yu[10];//每种余下的数目
28 int trial[10];
29 int b,g,n,s,tem,cnt;
30 int main()
31 {
32     while(scanf("%d%d%d",&g,&b,&s)&&!(g==0&&b==0&&s==0))
33     {
34         memset(dp,0,sizeof(dp));
35         memset(num,0,sizeof(num));
36         for(int i=0;i<b;i++)
37         {
38             scanf("%d",&n);
39             for(int j=1;j<=n;j++)
40             {
41                 scanf("%d",&tem);
42                 ++num[i][tem];
43             }
44         }
45         int total=(1<<b)-1;
46         for(int i=1;i<=total;i++)
47         {
48             dp[i]=-INF;
49             memset(yu,0,sizeof(yu));
50             for(int j=0;j<b;j++)
51             {
52                 if(!(i&(1<<j)))
53                 {
54                     for(int q=1;q<=g;q++)
55                         yu[q]+=num[j][q];
56                 }
57             }
58             for(int q=1;q<=g;q++)
59                 yu[q]%=s;
60             for(int j=0;j<b;j++)
61             {
62                 if(i&(1<<j))
63                 {
64                     cnt=0;
65                     memcpy(trial,yu,sizeof(yu));
66                     for(int q=1;q<=g;q++)
67                     {
68                         trial[q]+=num[j][q];
69                         while(trial[q]>=s)
70                         {
71                             ++cnt;
72                             trial[q]-=s;
73                         }
74                     }
75                     if(cnt)
76                         dp[i]=max(dp[i],dp[i^(1<<j)]+cnt);
77                     else
78                         dp[i]=max(dp[i],-dp[i^(1<<j)]+cnt);
79                 }
80             }
81         }
82         printf("%d\n",dp[total]);
83     }
84 }
时间: 2024-08-03 10:28:46

(状压dp)HDU 4778 Gems Fight!的相关文章

[博弈dp] hdu 4778 Gems Fight

给出g种颜色的宝石,然后有B个背包,S代表到时候每种颜色的宝石凑齐S个能变成一个魔法石 然后B行数输入,每个包里有哪些宝石 然后A,B轮流拿包,每个包只能拿一次,拿出包把宝石放地上. 如果能变成魔法石则拿走魔法石,下一次还这个人拿包,没变成则换人. 魔法石的个数就是获得分数,问两人最优的时候分差是多少. 思路: 只有21个包,状压dp. 然后发现不管顺序如何 最后构成的魔法石的个数是一定的. 然后在不同的二进制状态下,所剩在地面上的宝石是一定的. 那么就可以dp[i] 代表i这个状态下 先手取所

HDU 4778 Gems Fight!(dp)

HDU 4778 Gems Fight! 题目链接 题意:有n个背包,包里有一些宝石,现在爱丽丝和你轮流选背包,把包里宝石丢到锅中,然后如果锅中有宝石数量到s个,就会得到魔法石,并且可以继续选背包,两人都按最优策略去取,问最后两人魔法石会差多少. 思路:dp,dp[s]表示选背包状态为s时候的值,然后去记忆化搜索即可,注意如果当前生成魔法石就继续加,否则就减即可 代码: #include <stdio.h> #include <string.h> #include <algo

hdu 4778 Gems Fight! 状压dp

转自wdd :http://blog.csdn.net/u010535824/article/details/38540835 题目链接:hdu 4778 状压DP 用DP[i]表示从i状态选到结束得到的最大值 代码也来自wdd 1 /****************************************************** 2 * File Name: b.cpp 3 * Author: kojimai 4 * Creater Time:2014年08月13日 星期三 11时

状压DP [HDU 3001] Travelling

Travelling Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4166    Accepted Submission(s): 1339 Problem Description After coding so many days,Mr Acmer wants to have a good rest.So travelling is

状压DP [HDU 1074] Doing Homework

Doing Homework Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5472    Accepted Submission(s): 2311 Problem Description Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lo

hdu 4778 Gems Fight!

第一次写状压dp-- 题意:http://blog.csdn.net/dyx404514/article/details/15506601 状压dp+博弈吧-- #include<iostream> #include<map> #include<string> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #include<q

[AC自动机+spfa+状压dp] hdu 3247 Resource Archiver

题意: 给n个本源串,m个病毒串 求一个最多的长度的单词包含所有的本源串并不包含任意一个病毒串 串均为01串 思路: 只有10个本源串 一开始想的是直接建立完trie图 然后在图上直接spfa 结果发现 dis[60005][1030] 超内存了 这个时候就要想到 其实只有节点的mark值大于0的节点是我们需要用的 就是那些含有状压权值的节点 那么我们先记录下这些节点是哪些 然后发现其实这些不到100个节点 所以跑100遍spfa 求出两两之间的最短路 然后用这个距离 去状压dp 数组就成了 d

hdu 4778 Gems Fight!(状态压缩+博弈+记忆化)

Gems Fight! Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others) Total Submission(s): 1383    Accepted Submission(s): 587 Problem Description Alice and Bob are playing "Gems Fight!": There are Gems of G differe

[AC自动机+状压dp] hdu 4534 郑厂长系列故事——新闻净化

题意:中文的题目,意思就是说有很多串,每个串都有权值,权值为999的串必须出现,-999的串必须不出现.权值在-999~999之间. 然后必须出现的串不超过8个.然后给一个全为小写目标串,问最少需要删除多少个字母才能够保证必须出现的串都出现,次数一样保证权值最大.输出次数和权值. 然后根据样例,那些必须出现的串,其实权值是0. 思路: 很明显一开始建自动机构成trie图,但是需要注意的就是mark和sum的更新.个人是把所有中间的节点的sum全部赋值成了-inf. 接着只有8个必须出现的串,所以