G - Nim plus Gym - 102878G(博弈题,dp做法(类似背包))

题意:俩个人,总共有n个球,每个人每次只能拿a[i]个球,每个人分别有m 个a[i],题目保证a[i]单调递增,当谁不能拿球的时候他就输了。
题目:https://vjudge.net/contest/413430#problem/G

题解: 一位大佬朋友写的代码,本菜鸡只是理解后翻译了一下。
这里的dpl和dpm的值只有0和1,代表桌子上剩余i个球的时候,这个时候谁去拿,他是会输还是会赢,所以会有dpl[i]=dpm[i]的情况,这个时候谁去拿谁都能保证自己赢,就看谁先手了,因为龙龙是先手,所以这种情况龙龙一定会赢。else if(dpm[i-lo[j]]==0)这里进行判断的时候,i-lo[j]是一定比i小的,这个时候毛毛是赢还是输的状态是已经被判断过的,所以这么一直递推下去,就会有结果。

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

int lo[120];//表示longlong每次能够拿的球
int ma[120];//表示maomao每次能够拿的球
int dpl[5100];//只有1和0俩个值,剩余i个球的时候,这个时候龙龙去拿是输还是赢
int dpm[5100];//只有1和0俩个值,剩余i个球的时候,这个时候毛毛去拿是输还是赢

int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1; i<=m; i++)
    {
        cin>>lo[i];
    }
    for(int i=1; i<=m; i++)
    {
        cin>>ma[i];
    }
    for(int i=1; i<=n; i++) //从1到n分别枚举剩i个球的时候这个时候谁去拿谁是输还是赢,
    {
        int flag=0;  //为0的时候代表这个时候谁去拿谁输
        for(int j=1; j<=m; j++)//遍历龙龙能够拿的数量
        {
            if(lo[j]>i)//当它拿的数量大于剩余的球的时候break
            {
                break;
            } //剩余i个球,这个时候龙龙如果拿走lo[j]个后,剩余的球毛毛去拿会不会输,
            else if(dpm[i-lo[j]]==0)//如果会的话,那么就跳出,i这个时候龙龙去拿,龙龙就赢
            {   //这个时候可能毛毛去拿,毛毛赢,那么遍历龙龙可以去拿的每一种情况,如果每一种情况,毛毛都可以赢
                flag=1//那么剩余i的时候龙龙去拿,龙龙就输了,如果存在一个毛毛输的情况,那么龙龙就走这种情况,龙龙就赢
                break;
            }
        }
        if(flag==1)dpl[i]=1;//如果龙龙可以赢,就标记龙龙赢
        flag=0;
        for(int j=1; j<=m; j++) //这里和上面龙龙的情况一样,只不过是换了个人
        {
            if(ma[j]>i)
            {
                break;
            }//遍历毛毛拿走ma[j]个球后,龙龙是否输,如果有一种情况是龙龙输了,那么在剩余i个球的时候
            else if(dpl[i-ma[j]]==0)//毛毛去拿,毛毛就可以赢,否则毛毛就输
            {
                flag=1;
                break;
            }
        }
        if(flag==1)dpm[i]=1;
    }
    //因为龙龙是先手,看一下桌子上剩余n个球的时候,龙龙去拿是输还是赢
    if(dpl[n])printf("Long Long nb!\n");
    else printf("Mao Mao nb!\n");

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值