题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5754
题目大意:
4种棋子,象棋中的 1王,2车,3马,4后,选其一,B和G轮流走,不能往左上走,一开始棋子在(1,1),谁先走到(n,m)谁赢,无法走动算平局D。
(n,m<=1000,case<=1000)
题目思路:
【博弈论】
这题博弈论。怎样都输为必败,只能走到必败的为必胜。
王:(王可以横竖斜走一格)如果n个m均为奇数先手必败,否则必胜。
从3x3格子看,当n和m均为奇数时先手必败,而且人总有办法一步从非均为奇走到均为奇。
车:(横竖走,格数不受限制)n=m先手必胜,否则后手必胜。
Nim问题。把横纵坐标看作两堆石子,每次可以从一堆取任意个。
马:(两横一竖,两竖一横)(n+m)%3!=2无解,m=n时先手胜,m=n+1或者n=m+1时后手胜,否则平局。
因为如果m=n,那么先手-2-1,后手就可以-1-2,重新回到m=n,而相差为1的时候先手把大的-2小的-1就到m=n的情况。
后:(横竖斜都可以走,格数不受限制)威佐夫博弈。有公式我不会推。只能找规律了。
把横纵坐标看作两堆石子,可以从任意一堆取任意个,或者从两堆同时取任意个,问谁先取完。
先n--,m--,先手必败局面(奇异局势)。前几个奇异局势:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。
看出a0=b0=0,ak是未在前面出现过的最小自然数,而bk=ak+k。
1 // 2 //by coolxxx 3 // 4 #include<iostream> 5 #include<algorithm> 6 #include<string> 7 #include<iomanip> 8 #include<memory.h> 9 #include<time.h> 10 #include<stdio.h> 11 #include<stdlib.h> 12 #include<string.h> 13 //#include<stdbool.h> 14 #include<math.h> 15 #define min(a,b) ((a)<(b)?(a):(b)) 16 #define max(a,b) ((a)>(b)?(a):(b)) 17 #define abs(a) ((a)>0?(a):(-(a))) 18 #define lowbit(a) (a&(-a)) 19 #define sqr(a) ((a)*(a)) 20 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b)) 21 #define eps (1e-8) 22 #define J 10000000 23 #define MAX 0x7f7f7f7f 24 #define PI 3.1415926535897 25 #define N 1004 26 using namespace std; 27 typedef long long LL; 28 int cas,cass; 29 int n,m,lll,ans; 30 int f[N<<1]; 31 void work1() 32 { 33 if(n&1 && m&1)puts("G"); 34 else puts("B"); 35 } 36 void work2() 37 { 38 if(n==m)puts("G"); 39 else puts("B"); 40 } 41 void work3() 42 { 43 if((n+m)%3!=2)puts("D"); 44 else if(m==n)puts("G"); 45 else if(abs(n-m)==1)puts("B"); 46 else puts("D"); 47 } 48 void work4() 49 { 50 if(f[n]==m)puts("G"); 51 else puts("B"); 52 } 53 int main() 54 { 55 #ifndef ONLINE_JUDGE 56 // freopen("1.txt","r",stdin); 57 // freopen("2.txt","w",stdout); 58 #endif 59 int i,j,x; 60 for(i=1,j=0;i<=1000;i++) 61 { 62 if(f[i])continue; 63 f[i]=i+j;f[i+j]=i; 64 j++; 65 } 66 for(scanf("%d",&cas);cas;cas--) 67 // for(scanf("%d",&cas),cass=1;cass<=cas;cass++) 68 // while(~scanf("%s",s)) 69 // while(~scanf("%d",&n)) 70 { 71 scanf("%d%d%d",&cass,&n,&m); 72 if(cass==1)work1(); 73 else if(cass==2)work2(); 74 else if(cass==3)work3(); 75 else if(cass==4)work4(); 76 } 77 return 0; 78 } 79 /* 80 // 81 82 // 83 */