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;
}
标签:Nim,int,lo,Gym,龙龙,毛毛,102878G,时候,个球 来源: https://blog.csdn.net/Are_you_ready/article/details/111499976