『HDU 5754』Life Winner Bo

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

题意:给你国际象棋的4种棋子(王,后,马,车),选择其中一种,给你一个棋盘**(N*M)谁能先走到 (N,M)的谁先赢,否则就打平.注意:假设当前棋(x,y),下一步在( x’,y’)**,那么 (x’>=x, y’>=y)

个人感想:这道题我比赛的时候也是队友想到了…妈的全程打酱油.可能博弈题刷得不多啊.反正记住,棋盘问题都可以转化为取石子问题…我就不用一个一个情况的去猜了.我以前也记过这结论.可是我居然忘了.

:通过手写几下就可以发现规律,凡是两个都是奇数的必输.

:威佐夫博弈.具体看一下别人的文章,详细的过一遍,网上很多,我不推荐了,选适合自己的吧.

:赛后我才发现可以推公式 (2,1)x+(1,2)y=(N-1,M-1);那么分开就可以得到二元一次方程
x=(2M-N-1)/3;
y=(2N-M-1)/3;
如果有任意一种情况不能整除,或者解**<0**,那么都是D.
如果两种情况都能整除,而且abs(x-y)=1;那么是必胜态
如果两种情况都能整除,而且abs(x-y)=0;那么是必输态
如果两种情况都能整除,而且abs(x-y)>=2;那么是D态,因为有人会宁愿打成平局,也不能让某方赢

:最简单的博弈Nim博弈.

分析:普通博弈+威佐夫博弈+Nim博弈.

代码:

/* Author:GavinjouElephant
 * Title:
 * Number:
 * main meanning:
 *
 *
 *
 */

//#define OUT
#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define Clear(x) memset(x,0,sizeof(x))
const int INF=0x3f3f3f3f;
int role,N,M;
void solve()
{
    if(N>M)swap(N,M);

    if(role==1)//王
    {
        if(N%2&&M%2)printf("G\n");
        else printf("B\n");
        return;
    }
    if(role==2)//车
    {
        if(N^M)printf("B\n");
        else printf("G\n");
        return ;
    }
    if(role==3)//马
    {
        if((2*N-M-1)%3||(2*M-N-1)%3||(2*N-M-1)<0)
        {
            printf("D\n");
            return ;
        }
        int x=(2*M-N-1)/3;
        int y=(2*N-M-1)/3;
        int k=abs(x-y);
        if(k>=2){printf("D\n");}
        else if(k==1){printf("B\n");}
        else if(k==0){printf("G\n");}
        return ;
    }
    if(role==4)//后
    {
        N-=1;
        M-=1;

        int k=(M-N)*((sqrt(5)+1)/2);
        if(k==N)printf("G\n");
        else printf("B\n");
        return ;
    }
}
int main()
{
#ifdef OUT
    freopen("coco.txt","r",stdin);
    freopen("lala.txt","w",stdout);
#endif
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&role,&N,&M);
        solve();
    }

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值