Life Winner Bo
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2946 Accepted Submission(s): 1082
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.
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
http://acm.hdu.edu.cn/showproblem.php?pid=5754
题意就是给一个端点,有四种棋子,看谁先走到谁赢,不然就是平局,每种棋子均有自己的走法,但要求只能向右向下走
可以分别看作四种不同的博弈,和我一开始想着暴力打表找规律完全不同,怎么做都得有道理的啊
1. 两堆石头,n,m,一次从其中一堆取出一个或者从两堆中各取出一个,谁先到(0,0)谁就赢
(0,0)对应的是(偶数,偶数)的状态
要赢就是自己下一步的状态是(偶数,偶数)
而(偶,偶)经过转换一步只能到(偶,奇) (奇,偶) (奇,奇)
这三个状态一步均可到(偶,偶) 所以处于(偶,偶)的是先手必输的
在这里,要走n-1 和 m-1步,就是说n-1 m-1都是偶数(也可以判断n m都是奇数),先手必输,否则先手必赢
2.Nimm博弈模型,从两堆中取,个数不限,取到最后一个的赢
异或之后结果为0的话后手必赢,否则先手必赢
3. 从一堆取一个,从另一堆取两个 ,或者相反 ,这个时候明显(3*k,3*k)是一种先手必输的状态,
先手要想赢就得使对手处于这个状态,如果两堆石头的个数为(3*k+1 , 3*k+2)或者(3*k+2, 3*k+1)
那么先手必胜,否则为平局
4.威佐夫博弈模型
威佐夫博弈(Wythoff Game):
有两堆各若干的物品,两人轮流从其中一堆取至少一件物品,至多不限,或从两堆中同时取相同件物品,规定最后取完者胜利。
直接说结论了,若两堆物品的初始值为(x,y),且x<y,则另z=y-x;
记w=(int)[((sqrt(5)+1)/2)*z ];
若w=x,则先手必败,否则先手必胜。
讨论完就很容易写了
#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int type,n,m,terms;
scanf("%d",&terms);
while(terms--)
{
scanf("%d%d%d",&type,&n,&m);
n--;
m--;
if(type == 1)
{
if(n%2==0 && m%2==0)
printf("G\n");
else
printf("B\n");
}
else if(type == 2)
{
int temp=0;
temp^=n;
temp^=m;
if(!temp)
printf("G\n");
else
printf("B\n");
}
else if(type == 3)
{
if(n==m && m%3==0)
printf("G\n");
else if(abs(m-n)==1 && (min(m,n)-1)%3==0)
printf("B\n");
else
printf("D\n");
}
else if(type == 4)
{
if(n>m)
swap(n,m);
int temp=floor( (m-n) * (sqrt(5) + 1)/2.0 );
if(temp == n)
printf("G\n");
else
printf("B\n");
}
}
return 0;
}