hdu5754 - 组合博弈

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5754

思路:

具体走法在代码中标注。

type==1:找规律可以找到,若横、纵坐标都是奇数那么先手必败,(看别人的题解说是巴什博奕,但不知道为啥qwq)

type==2:相当于基本的nim博弈,只能横、竖走,横走n-1,竖走m-1,把他们想象成取石子

type==3:走日分为两种走法,第一种向右,第二种向下,设向右走x个日,向下走y个,那么2x+y=m-1,x+2y=n-1

解得:x=(2m-1-n)/3,y=(2n-m-1)/3,x+y=(n+m-2)/3,若x+y不是整数,那么输出D,没有赢家。

设t=abs(x-y),若t==1那么先手必定会赢,若t==0那么后手一定会赢,若t>=2,必定有人制造平局。

type==4:威佐夫博弈

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#include<set>
#include<string>
#include<cstring>
#define ll long long
using namespace std;
const int N=100005;
int dep[N],a[N];

int main(){
    int t,k,n,m;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d",&k,&n,&m);
        if(k==1){//王走横、直、斜,每次一步
            if(n%2==0||m%2==0){
                printf("B\n");
            }
            else printf("G\n");
        }
        if(k==2){//横竖均可走不受限制
            int ans=0;
            ans^=(n-1);
            ans^=(m-1);
            if(ans)printf("B\n");
            else printf("G\n");
        }
        if(k==3){//马走日
            if((n+m-2)%3)printf("D\n");
            else {
                int r=(2*m-n-1)/3,d=(2*n-m-1)/3;
                if(abs(r-d)>=2){
                    printf("D\n");
                }
                else if(abs(r-d)==1)printf("B\n");
                else printf("G\n");
            }
        }
        if(k==4){//横竖斜均可走不受限制
            int x=n-1,y=m-1;
            if(x>y)swap(x,y);
            int tmp=floor((y-x)*(1+sqrt(5.0))/2.0);
            if(tmp==x)printf("G\n");
            else printf("B\n");
        }
    }
}

猜你喜欢

转载自blog.csdn.net/m0_37579232/article/details/82788417