【博弈论】HDU 5754 Life Winner Bo

题目链接:

  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 */
View Code

 

posted @ 2016-08-13 23:36  Cool639zhu  阅读(177)  评论(0编辑  收藏  举报