http://acm.hdu.edu.cn/showproblem.php?pid=5754
题意:
给一个国际象棋的棋盘,起点为(1,1),终点为(n,m),现在每个棋子只能往右下方走,并且有4种不同的棋子,棋子的走法与国际象棋走法一致。问最后谁能取得胜利。
思路:
首先推荐一个博客http://www.matrix67.com/blog/archives/6784,这里面对这问题有很好的讲解。
我还是简单解释一下:
①king:
国王每次只能横、竖、斜走一格,这个很好分析,(x,y)如果连个都是奇数,那肯定是必败状态,否则就是必胜状态。
②rook:
车每次能横、竖走任意格,这个问题的模型其实和拿石子是一样的,是个尼姆博弈,有两堆石子,每次可以选择在任意一堆中拿走任意数量的石子,那么这里车的坐标(x,y)就对应了两堆石子的石子数量。如果x=y,那么先手无论拿多少,另一个人总可以在另一堆石子中拿相同的石子数,这样到最后肯定是先手败,如果x!=y则是先手必胜。
③kight:
骑士的走法是先往一个方向走2格,再往其垂直方向走1格。首先通过方程求解的话可以得出(n+m-2)必须得是3的倍数,否则就是平局。如果n=m,那么先手无论怎么操作,另一个人都可以走相反的方向,这样每轮过后棋子的x,y值始终是相等的,此时先手必败。如果n=m+1,或者m+1,此时先手可以一步使得棋子坐标x,y值相等,这就和上一种情况一样了,此时先手必胜。除此之外的情况都是平局,因为玩家可以乱走,使得最后无法到达终点。
④queen:
皇后能横、竖、斜走任意格,这就相当于有两个石子堆,每次可以在任意一堆中拿走任意的石子数量或者在两个堆中拿走相同数量的石子数。这就是一个明显的威佐夫博弈,直接套用黄金分割定律。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 typedef pair<int,int> pll; 14 const int INF = 0x3f3f3f3f; 15 const int maxn=100+5; 16 17 int type,n,m; 18 19 int main() 20 { 21 //freopen("in.txt","r",stdin); 22 int T; 23 scanf("%d",&T); 24 while(T--) 25 { 26 scanf("%d%d%d",&type,&n,&m); 27 if(type==1) 28 { 29 if((n&1) && (m&1)) puts("G"); 30 else puts("B"); 31 } 32 else if(type==2) 33 { 34 if(n==m) puts("G"); 35 else puts("B"); 36 } 37 else if(type==3) 38 { 39 if((n+m-2)%3==0) 40 { 41 if(n<m) swap(n,m); 42 if(n==m) puts("G"); 43 else if(n-m==1) puts("B"); 44 else puts("D"); 45 } 46 else puts("D"); 47 } 48 else 49 { 50 if(n==m) puts("B"); 51 else 52 { 53 if(n>m) swap(n,m); 54 n--;m--; 55 int w=(int)(((sqrt(5)+1)/2.0)*(m-n)); 56 if(w==n) puts("G"); 57 else puts("B"); 58 } 59 } 60 } 61 return 0; 62 }