hdu 5754 Life Winner Bo 博弈论
Life Winner Bo
题目连接:
http://acm.hdu.edu.cn/showproblem.php?pid=5754
Description
Bo is a "Life Winner".He likes playing chessboard games with his girlfriend G.
The size of the chessboard is N×M.The top left corner is numbered(1,1) and the lower right corner is numberd (N,M).
For each game,Bo and G take turns moving a chesspiece(Bo first).At first,the chesspiece is located at (1,1).And the winner is the person who first moves the chesspiece to (N,M).At one point,if the chess can't be moved and it isn't located at (N,M),they end in a draw.
In general,the chesspiece can only be moved right or down.Formally,suppose it is located at (x,y),it can be moved to the next point (x′,y′) only if x′≥x and y′≥y.Also it can't be moved to the outside of chessboard.
Besides,There are four kinds of chess(They have movement rules respectively).
1.king.
2.rook(castle).
3.knight.
4.queen.
(The movement rule is as same as the chess.)
For each type of chess,you should find out that who will win the game if they both play in an optimal strategy.
Print the winner's name("B" or "G") or "D" if nobody wins the game.
Input
In the first line,there is a number T as a case number.
In the next T lines,there are three numbers type,N and M.
"type" means the kind of the chess.
T≤1000,2≤N,M≤1000,1≤type≤4
Output
For each question,print the answer.
Sample Input
4
1 5 5
2 5 5
3 5 5
4 5 5
Sample Output
G
G
D
B
Hint
题意
给你个棋盘,一开始棋子在(1,1)位置,两个人开始玩,只能往右下方向走
谁先走到(n,m)就算胜利,棋子走不到,就算平局。
一共棋子有四种:车,马,国王,皇后
走棋规则是按照国际象棋走法走的。
题解:
国王我没想清楚,我就暴力sg打表的。
车的话,就相当于有两堆石头,一堆n-1个石子,一堆m-1个石子,然后可以拿任意堆任意个。是一个标准的nim博弈
皇后的话,和车一样考虑,就是可以拿任意堆任意个,或者拿两堆同时拿任意个,是一个标准的威佐夫博弈。
马就比较烦的,他到终点的步数是唯一确定的,所以只用判断奇数偶数就好了。但是比较烦的是,如果这个人觉得他会输,他就会使得这局比赛走向平局,就走到一个不可能走到终点到位置。
这个我们手玩了一下,发现只要不在对角线位置的点,输家就可以使得比赛走向平局。(就是abs(n-m)>1的时候,一定是平局)
代码
#include <bits/stdc++.h>
using namespace std;
int dp[1010][1010];
int main()
{
memset(dp,-1,sizeof(dp));
dp[1][1]=0;
for(int i=1;i<=1000;i++)
{
for(int j=1;j<=1000;j++)
{
int a=dp[i][j-1],b=dp[i-1][j],c=dp[i-1][j-1];
if(a!=0&&b!=0&&c!=0)
{
dp[i][j]=0;
continue;
}
if(a!=1&&b!=1&&c!=1)
{
dp[i][j]=1;
continue;
}
if(a!=2&&b!=2&&c!=2)
{
dp[i][j]=2;
continue;
}
dp[i][j]=3;
}
}
int T;
scanf("%d",&T);
while(T--)
{
int n,m,type;
scanf("%d%d%d",&type,&n,&m);
if(type==1)
{
if(dp[n][m]) printf("B\n");else printf("G\n");
}
if(type==2)
{
int x=n-1,y=m-1;
int z=x^y;
if(z) printf("B\n");else printf("G\n");
}
if(type==3)
{
if(n>m) swap(n,m);
int x=n-1,y=m-1;
if((x*2<y)||(y*2<x)||(x*2-y)%3!=0||(y*2-x)%3!=0) printf("D\n");
else
{
int z=(x*2-y)/3+(y*2-x)/3;
if(z&1)
{
if(z+z/2>=n) printf("D\n");else printf("B\n");
}
else
{
if(z+z/2>=n) printf("D\n");else printf("G\n");
}
}
}
if(type==4)
{
int a=n-1,b=m-1,t,d;
if ( a > b ) {
t = a;
a = b;
b = t;
}
d = b - a;
t = floor( d * ( sqrt(5.0) + 1 ) / 2 );
printf( (t == a) ? "G\n" : "B\n" );
}
}
return 0;
}