博弈结论记录

一、巴什博奕:

只有一堆n个物品,两个人轮流从中取物,规定每次最少取一个,最多取m个,最后取光者为胜。

结论:

见代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#define FRE() freopen("in.txt","r",stdin)

using namespace std;
int n,m;

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        if(n % (m+1) == 0)
            printf("先手输\n");
        else
            printf("先手赢\n");
    }
    return 0;
}

二、 威佐夫博弈:

有两堆各若干的物品,两人轮流从其中一堆取至少一件物品,至多不限,或从两堆中同时取相同件物品,规定最后取完者胜利。

结论:

两堆物品的数量各是a、b,则令k = abs(b - a),t = min(a,b),计算temp = (sqrt(5.0)+1)/ 2.0,如果k * temp = t,则先手输,反之先手赢。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#define FRE() freopen("in.txt","r",stdin)

using namespace std;
const int maxn = 1e4;
int a,b;

int main()
{
    //FRE();
    double temp = (sqrt(5.0) + 1) / 2.0;
    while(~scanf("%d%d",&a,&b))
    {
        if(a > b) swap(a, b);
        int k = b - a;
        if(a == (int)(k*temp))//注意数据类型的转换
            printf("0\n");
        else
            printf("1\n");
    }
    return 0;
}

三、尼姆博奕:

有任意堆物品,每堆物品的个数是任意的,双方轮流从中取物品,每一次只能从一堆物品中取部分或全部物品,最少取一件,取到最后一件物品的人获胜。

结论:

把所有堆得物品的个数连续求异或(^运算),如果结果为0,先手输,不为0时,先手赢。

例题:HDU2176

当序列的连续异或值为k(k != 0)时,假设其中的某个元素a,当a > a ^ k 时,将a改为a^k,可以使序列的异或值变为0。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <set>
#define INF 0x3f3f3f3f

using namespace std;
typedef long long ll;
const int maxn = 200000;
int buf[maxn];


int main()
{
    int n;
    while(scanf("%d",&n) && n)
    {
        int temp = 0,mmin = INF;
        for(int i = 0; i < n; i++)
        {
            scanf("%d",&buf[i]);
            mmin = min(mmin, buf[i]);
            temp ^= buf[i];
        }
        if(temp == 0)
            printf("No\n");
        else
        {
            printf("Yes\n");
            for(int i = 0; i < n; i++)
            {
                if( buf[i] > (buf[i]^temp) )
                    printf("%d %d\n",buf[i],buf[i]^temp);
            }
        }
    }
    return 0;
}

四、斐波那契博弈:

有一堆物品,两人轮流取物品,先手最少取一个,至多无上限,但不能把物品取完,之后每次取的物品数不能超过上一次取的物品数的二倍且至少为一件,取走最后一件物品的人获胜。

结论

先手胜利当且仅当这堆物品的数目不是斐波那契数列中的数字。(该类问题可以打表解决)

例题HDU-2516

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <set>
#define INF 0x3f3f3f3f

using namespace std;
typedef long long ll;
const int maxn = 100000;

ll buf[maxn];
set<ll> s;
void init()
{
    buf[0] = buf[1] = 1;
    for(int i = 2; i < maxn; i++)
    {
        buf[i] = buf[i - 1] + buf[i - 2];
        s.insert(buf[i]);
    }
}


int main()
{
    ll x;
    init();
    while(scanf("%lld",&x) && x)
    {
        if(s.count(x))
            printf("Second win\n");
        else
            printf("First win\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sykai1/article/details/81482714
今日推荐