poj2068:Nim——题解

10 篇文章 0 订阅
7 篇文章 0 订阅

(好的说好的故事)
那么话说在那遥远的国度,勇者和路由器偶然间得到了一个藏宝图。
但当他们到达藏宝图所指向的山洞中的时候,打开宝箱,却昏昏睡了过去……
醒来之后,他发现自己被人囚禁在了一个地牢中,与之相同的还有工厂厂长kekeke,某不愿透露姓名的去采胡萝卜的兔,以及连照相馆馆长都被抓了进来。
门外传来了一阵笑声。
“哈哈哈……你们都来了啊!,和我一起玩一个游戏吧,赢了你们就可以走了”
“不过,规则要按我说的来!”

——————————————

首先,dp【i】【j】代表的意思是第i个人在只剩下j个石头的时候对于当前的人所在队伍是否必胜,如果必胜为1,否则为0;
(初始化dp为-1 用来判断是否已经读到了这个dp)
然后,我们枚举当前人可以拿石子的所有个数。
此时我们明白一个问题,只要当前的人的下家是必败的,那么我们这个人就是必胜的。
反之只要是必胜的话那么我们这个人就是必败的。
然后这样慢慢的从最后一个人推回到第一个人,此时输出第一个人是必胜的还是必败的就ok啦
怎样是不是很简单那(并没有)

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
int dp[30][8205]={0};
int a[22]={0};
int n,s;
int dfs(int ren,int shi){
    if(dp[ren][shi]!=-1)return dp[ren][shi];
    for(int i=1;i<=min(shi,a[ren]);i++){
        int t;
        t=(ren+1)%(2*n);
        if(dfs(t,shi-i)==0)return dp[ren][shi]=1;
    }
    return dp[ren][shi]=0;
}
int main()
{
    scanf("%d",&n);
    while(n!=0){
        scanf("%d",&s);
        memset(a,0,sizeof(a));
        memset(dp,-1,sizeof(dp));
        for(int i=0;i<2*n;i++)dp[i][0]=1; 
        for(int i=0;i<2*n;i++)scanf("%d",&a[i]);
        printf("%d\n",dfs(0,s));
        scanf("%d",&n);
    }
    return 0;
}

后记:话说回来勇者一行人在尝试了n多次后终于赢了,不过当他们走出牢房的时候
……前途仍然一片渺茫,下面仍然是一间牢房

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值