HDU 5754 Life Winner Bo(多校3 各种博弈)

来源:互联网 发布:中国大数据协会 编辑:程序博客网 时间:2024/06/04 20:04

HDU 5754博弈

题意国际象棋,有四个人物。从(n,m)走到(1,1),走到(1,1)的人赢,先手赢输出B,后手赢输出G,平局输出D

思路:可以先认为从(1,1)出发,到(n,m)点。本题就是各种博弈的汇总。

四种棋子的规则如下:(做题时确实不知道国际象棋的走法就百度了一下)

1、王(King):横、竖、斜都可以走,每次限走一格

2、车(Rook):横、竖均可走,不能斜走,格数不受限制,除王车易位的情况下,平时不能越子

3、马(Knight):每步棋先横走或竖走一格,再斜走一格(或者横两格竖一格,竖两格横一格),可以越子

4、后(Queen):横、竖、斜都可以走,格数不受限制,但不能越子

第一种很明显(1,1)是必败点,可以走到必败点的都是必胜点,而只能走到必胜点的都是必败点,所以很容易得出结论:n,m都为偶数则先手必败。

第二种把这个问题看做是两堆石子,取石子问题,是尼姆博弈,异或为0即相等的时候先手必败。

第三种先n,m如果if(m==n&&m%3==1)的倍数一定是先手输;如果是if((m%3==0&&n==m-1)||(n%3==0&&m==n-1)),则先手必胜,因为可以一步走到必败点,必胜;其余情况都是平局,因为如果一方存在赢的情况,另一方可以不走那步,把小的数-2,大的数-1,往墙上靠,谁也赢不了肯定是平局。


第四种也是看做两堆石子,取石子问题,是威佐夫博弈。用威佐夫博弈时注意是对m--,n--进行操作应为queue初始是在(1,1)点,相当于剩余的石子数是m--,n--。比赛时忘了这一点,debug了好长时间。


附AC代码:

#include <iostream>#include <stdio.h>#include <math.h>#include <algorithm>#include <stack>#include <cstring>using namespace std;int n,m;void pying()///输出赢{    puts("B");}void pshu()///输出输{    puts("G");}void pping()///输出平{    puts("D");}///找规律,n,m都为偶数则先手必败///国王,每次只能向左或向下或左下移动一个格void king(){    if((n&1)&&(m&1))        pshu();    else        pying();}/*把这个问题看做是两堆石子,取石子问题,是尼姆博弈,异或为0即相等的时候先手必败。其实直接找规律就好车,每次能沿着水平方向或竖直方向走任意距离*/void rook(){    if(m==n)        pshu();    else        pying();}void knight()///骑士只能走”日“字{    if(m==n&&m%3==1)        pshu();    else if((m%3==0&&n==m-1)||(n%3==0&&m==n-1))        pying();    else        pping();}///威佐夫博弈///皇后可以沿 水平方向或 竖直方向或 正方形的对角线方向移动任意距离void que(){    m--;    n--;    if(n<m)        swap(n,m);    int k=n-m;    int n=(int)(k*(1+sqrt(5))/2.0);    if(n==m)        pshu();    else        pying();}int main(){int T;scanf("%d",&T);while(T--){int flag;        cin >> flag >> m >> n;        if(flag==1) king();        else if(flag==2) rook();        else if(flag==3) knight();        else if(flag==4) que();}return 0;}


0 0
原创粉丝点击