Codeforces 786A Berzerk(博弈)

题目链接

很明显的博弈题目,但是昨天打比赛的时候就是一直想不出来,一直在纠结这个loop的情况到底要怎么定义,感觉到深深的挫败感,自己之前专门看了一段时间博弈也没有任何用处= =太菜了

今天看了一下题解,发现思路其实还是很简单的,对于每个点都有两种状态,a推到这里和b推到这里,我们可以知道,对于1这个位置,无论哪个人在面临这样的局面时,都是必败态,我们从这个点出发,如果这个点是必败态(0),那么对于所有能一步走到这个点的位置,都有必胜态;对于每个状态,只有当它的后续状态都为1时,这个点为必败态,所以我们可以从1出发,对于每个能走到这个点的状态本身进行一个数量的统计,如果这个num=它的可操作步数,就说明这个点为必败态。

我们可以通过bfs来解决。

#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
#define ll long long
#define CL(a) memset(a,0,sizeof(a))
#define maxn 7010
#define mod 2520
int dp[2][maxn],num[2][maxn];
int n;
vector<int> v[2];


void bfs()
{
    queue<pair<int,int> > que;
    que.push(make_pair(0,0));
    que.push(make_pair(1,0));
    while(!que.empty())
    {
        int p=que.front().first;
        int pos=que.front().second;
        int x=dp[p][pos];
        que.pop();
        if(x==0)
        {
            for(int i=0; i<v[!p].size(); i++)
            {
                int nxt=(pos-v[!p][i]+n)%n;
                if(dp[!p][nxt]==-1)
                {
                    dp[!p][nxt]=1;
                    que.push(make_pair(!p,nxt));
                }
            }
        }
        else
        {
            for(int i=0; i<v[!p].size(); i++)
            {
                int nxt=(pos-v[!p][i]+n)%n;
                if(dp[!p][nxt]!=-1) continue;
                if(num[!p][nxt]<v[!p].size()) num[!p][nxt]++;
                if(num[!p][nxt]==v[!p].size())
                {
                    dp[!p][nxt]=0;
                    que.push(make_pair(!p,nxt));
                }
            }

        }
    }

}

int main ()
{
    memset(dp,-1,sizeof(dp));
    memset(num,0,sizeof(num));
    cin>>n;
    for(int i=0; i<2; i++)
    {
        int k;
        cin>>k;
        for(int j=0; j<k; j++)
        {
            int m;
            cin>>m;
            v[i].push_back(m);
        }
    }
    dp[0][0]=dp[1][0]=0;
    bfs();
    for(int i=0; i<2; i++)
    {
        for(int j=1; j<n; j++)
        {
            if(dp[i][j]==0) cout<<"Lose"<<' ';
            else if(dp[i][j]==1) cout<<"Win"<<' ';
            else cout<<"Loop"<<' ';
        }
        cout<<endl;
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值