威佐夫博弈

入门题:POJ1067
威佐夫详解
例如,两堆石子,两种取法,要么在一堆中取任意数量,要么在两堆中取同等数量,取完者胜。
根据前人研究,先手的必败局为(m,n)【其中 min(m,n) == | m - n | *1.618】
在当前局势必胜的情况下,可以通过枚举差值使其满足必败局的条件,得到下一步的取法。

#include <iostream>
#include<cstdio>
#include<math.h>
using namespace std;
const double g = (sqrt(5.0) + 1) / 2;   //1.618  这种算法比较准确
bool validate(int a,int b){
    if(a > b)swap(a,b);
    int k = b - a;
    if(a == (int)(g * k)) return true; //注意int是下取整
    else return false;
}
int main(){
    int n,m;
    while(scanf("%d%d",&n,&m) != EOF){
        if(validate(n,m))printf("0\n");
        else {
                printf("1\n");
                //在两堆石子中同时取,从1枚举到最小数
                int a = min(n,m);
                int b = max(n,m);
                int ans = 0;
                //取完之后让对手面对必败局
                for(int i = 1; i <= a;++i){
                    if(validate(a-i,b-i)) printf("%d %d\n",a-i,b-i);

                }
                //仅从一堆中取
                for(int i = b - 1;i >= 0;--i){
                    if(validate(a,i))printf("%d %d\n",a,i);
                }
        }
    }

    return 0;
}

}

上一篇:Mysql之Your password does not satisfy the current policy requirements


下一篇:vue validate js