博弈综合

来源:互联网 发布:二季度出口数据 编辑:程序博客网 时间:2024/05/01 04:14

题目:hdu5754

题意有4种操作分别是:
1.king.每次横或者竖或者斜只能走一步
2.rook(castle).每次横或者竖能走若干步
3.knight.每步先横(竖)走一格,再斜走一格。或者每步先斜走一格,再横(竖)走一格
4.queen.每次横或竖或斜走若干步
然后这些操作对应的是国际象棋里面的一些操作(具体操作可以百度) 然后现在我们站在(1,1)点,要去往(N,M)点,按照国际象棋操作的时候只能往右或者往下走,然后有两个人进行按照规则进行操作,谁最先到达(N,M)点谁就胜出。

解答:1、再想想吧。有人说是巴什博弈?或者根据博弈的规律推?

          2、走到终点的时候,恰好横着走了m-1步,竖着走了n-1步。所以这个问题就可以转化为有两堆石子的Nim游戏。谁先拿完这两堆棋子谁就就赢。(两堆石子的数量为n-1和m-1)。

          3、这个每走一次相当于从一堆石子里面拿两个,从另一堆石子里面拿一个。如果石子的和不是3的倍数很显然不能拿完。

如果是,如果两个石子数目相同,那么先手必败,因为第一个人从第一个里面拿一个第二个里面拿两个,你就从第二个里面拿一个从第一个里面拿两个,石子数目仍然相同,最后拿没了。如果两堆石子的差为1的话,第一个人拿完让他们相等就到了奇异局势。

其他的情况,一个人想办法变成奇异局势另外一个人肯定会阻止最后的结果就是平局。

          4、也把它转化为两堆石子。两个人可以任选一堆拿一个,或者两堆同时拿一样数目的石子,谁先拿完谁赢。哦这就是典型的威佐夫博弈。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;int main(){    int T,k,m,n;    scanf("%d",&T);    while(T--)    {        int ans = 1;//先手赢        scanf("%d%d%d",&k,&m,&n);        if(k == 1)        {            if((m&1)&&(n&1))                ans = 0;        }        else if(k == 2)        {            if(((n-1)^(m-1)) == 0)                ans = 0;        }        else if(k == 3)        {            n--;            m--;            if((m+n)%3)                ans = 2;            else if(m == n)                ans = 0;            else if(m == n+1 || n == m+1)                ans = 1;            else                ans = 2;        }        else if(k == 4)        {            m--;            n--;            if(m > n)            {                int t = m;                m = n;                n = t;            }            int tmp = floor((n - m) * (sqrt(5.0)+1)/2);            if(tmp == m)                ans = 0;        }        if(ans == 0)        puts("G");        else if(ans == 1)        puts("B");        else if(ans == 2)        puts("D");    }    return 0;}



          

         

0 0
原创粉丝点击