hdu 4778【状态压缩+记忆化搜索】

本文探讨了GemsFight游戏的最优策略,分析了宝石收集和转换成魔力宝石的规则,通过动态规划算法计算先手与后手的得分差值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

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);
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值