HDU 2177 取(2堆)石子游戏 (威佐夫博弈)

题目思路:威佐夫博弈:

当当前局面[a,b]为奇异局时直接输出0

否则:

1.若a==b,输出(0 0);

2.将a,b不停减一,看能否得到奇异局,若有则输出;

3.由于 ak=q*k(q为黄金分割数)具有单调性,不断改变k的值,看是否可以得到奇异局,若有则输出。

其他的话,要注意一些细节。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#define INF 0x3f3f3f3f
#define MAXSIZE 100005

using namespace std;

void Game(int a,int b)
{
    double q=(1+sqrt(5.0))/2.0;//黄金分割数
    int k=b-a,n,m;
    if(a==(int)(k*q))
    {
        printf("0\n");
        return;
    }
    else
    {
        printf("1\n");
        if(a==b)
        {
            printf("0 0\n");
        }
        n=a;
        m=b;
        while(n && m)//同时取
        {
            n--;
            m--;
            k=m-n;
            if(n==(int)(k*q) && n!=m)
            {
                printf("%d %d\n",n,m);
                break;
            }
        }
        k=b-a;
        while(1)//单一堆取,k不断向下取
        {
            n=(int)(k*q);
            m=n+k;
            if(n<0 || m<0) break;
            if(n<a && m<b && ((a!=n || b!=m)||(a!=m || b!=n)) && ((n==a||n==b) || (m==a || m==b)))//要求a,b能且只能改变一个数
            {
                printf("%d %d\n",n,m);
                break;
            }
            k--;
        }
        k=b-a;
        while(1)//同理单取一堆,k不断向上取
        {
            n=(int)(k*q);
            m=n+k;
            if(n>a || m>b) break;
            if(n<=a && m<=b && ((a!=n || b!=m)||(a!=m || b!=n)) && ((n==a||n==b) || (m==a || m==b)))
            {
                printf("%d %d\n",n,m);
                break;
            }
            k++;
        }

    }

}

int main()
{
    int a,b;
    while(scanf("%d%d",&a,&b),a+b)
    {
        Game(a,b);
    }
    return 0;
}
View Code

 

posted @ 2017-01-14 15:39  声声醉如兰  阅读(179)  评论(0)    收藏  举报