博弈基础 三大博弈

Bash游戏

题目链接

有1堆石子,共n颗,每次可取1~k颗,先拿完者

若n%(k+1)==0,则先手必败

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n,k;
        scanf("%d%d",&n,&k);
        if(n%(k+1)==0)
            printf("B\n");
        else
            printf("A\n");
    }
}
View Code

Bash游戏_进阶

题目链接(这是个坑)

有1堆石子,共n颗,每次可取k(属于集合f)颗,先拿完者

打表找好规律就好了,下面是打表函数

#include<bits/stdc++.h>
using namespace std;

//const int N=;
int vis[100];
//int f[N]={};

int main()
{
    for(int i=1;i<90;i++)
        for(int j=0;f[j]<=i&&j<N;j++)
        {
            if(vis[i-f[j]]==0)
                vis[i]=1;
        }
    for(int i=0;i<90;i++)
        printf("i=%d:vis[i]=%d\n",i,vis[i]);
}
View Code

总结:此类博弈不需要考虑sg函数,只需要确定必胜态和必败态,解题思路一般为打败先打表找规律,而后找规律给出统一的公式。打表方式:给定初始条件,然后从低到高枚举某一状态的所有次态,若有存在必败次态,则当前状态为必胜态,否则当前状态必败。

===========================================================================================

Nim游戏

题目链接

有n堆石子,每堆有a[i]个石子,先拿完者

若异或和不为0,则先手必胜

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int n;
    cin>>n;
    int ans=0;
    while(n--)
    {
        int t;
        cin>>t;
        ans^=t;
    }
    if(ans==0)
        printf("B\n");
    else
        printf("A\n");
}
View Code

Nim游戏_进阶

题目链接

有n堆石子,每堆有a[i]个石子,先拿完者

若不全是单个石子成堆且异或和不为0,或者全是单个石子成堆且共有偶数堆,则先手必胜

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int n;scanf("%d",&n);
        int ans=0;
        bool flag=false;
        while(n--)
        {
            int t;
            scanf("%d",&t);
            ans^=t;
            if(t>1) flag=true;
        }
        if(flag&&!ans || !flag&&ans)
            puts("Brother");
        else
            puts("John");
    }
}
View Code

//总结:此类博弈一般需要考虑sg函数,  过段时间再填坑。。。。。。

===========================================================================================

Wythoff游戏

题目链接

有两堆石子,每次可以从一堆中取任意个或从2堆中取相同数量的石子,但不可不取,先拿完者

设少的一堆有a个,多的一堆有b个,k=(1+sqrt(5)/2.0,若a==floor((b-a)*k),则先手必败

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int T,a,b,t;
    double k=(1+sqrt(5))/2.0;
    cin>>T;
    while(T--)
    {
        scanf("%d%d",&a,&b);
        if(a>b) swap(a,b);
        t=b-a;
        printf("%c\n",a==(int)(t*k)?'B':'A');
    }
}
View Code

 

转载于:https://www.cnblogs.com/Just--Do--It/p/6409230.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值