HDU 3595 GG and MM

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3595


题意:两个人同时玩n组游戏,规则都相同,给定一组(x,y)(假设y>=x),每次操作可以在y中拿走x的整数倍变为(x,y-kx),两个人轮流进行,不能操作的那方算输。而同时玩n组游戏时,判断输赢的结果就是这n组游戏最后一组进行完的游戏的结果。


思路:这种类型属于Every-SG,既然这n组游戏只看最后结束那场的结果,所以对于先手必胜的局,先手肯定想拖延步数,使得游戏进行得更长一些;对于先手必败的局,先手肯定想快点结束这句游戏。所以我们打表计算此状态必胜/必败时,顺便计算次状态到达结束时的步数。


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;

#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)

#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
#define ULL unsigned long long
#define inf 0x7fffffff
#define mod 100000007
const int maxn = 1009;
int can[maxn][maxn];
int step[maxn][maxn];

int cal( int x , int y )
{
    if ( can[x][y] != -1 ) return can[x][y];
    if ( x > y ) swap(x,y);
    int m1,m2;
    m1 = maxn*maxn;
    m2 = 0;
    int ans = 0;
    int k = y / x;
    rep(i,1,k)
    {
        if ( cal( x , y - i * x ) ) //如果留给对手的状态必胜
            m1 = min( m1 , step[x][y-i*x] );//就取最小步数,尽快结束游戏
        else
        {
            m2 = max( m2 , step[x][y-i*x] );
            ans = 1;
        }
    }
    if ( ans )
        step[x][y] = step[y][x] = m2 + 1;
    else
        step[x][y] = step[y][x] = m1 + 1;
    return can[x][y] = can[y][x] = ans;
}

void init()
{
    Clean(step,0);
    Clean(can,-1);//记忆化搜索,-1表示未计算过。
    rep(i,0,1000) can[i][0] = can[0][i] = 0;
}

int main()
{
    int n;
    init();
    while( scanf("%d",&n) == 1 )
    {
        int ans = 0;
        int x,y;
        rep(i,1,n)
        {
            scanf("%d%d",&x,&y);
            cal(x,y);
            ans = max( ans , step[x][y] );//取最大步数
        }
        puts(ans&1?"MM":"GG");//如果是奇数步,一定是先手胜。
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值