1. 程式人生 > >(狀壓dp)HDU 4778 Gems Fight!

(狀壓dp)HDU 4778 Gems Fight!

ont magic fig urn turn sid several desc ant

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 }

(狀壓dp)HDU 4778 Gems Fight!