题目链接: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;
}