【POJ2068】Nim DP博弈

题意:

多组数据

两人轮流操作,n轮一循环,给出总石子数和这n轮每次两人能取的石子上限(下限为1)。

取到最后一颗者输。


比如

3 97 8 7 6 5 4 3

表示一循环有三轮,

可取的个数为:

第一轮 先手8 后手7

第二轮 先手6 后手5

第三轮 先手4 后手3

然后三轮每取完的话就进入下次循环。


数据范围自己看去吧。



题解:

DP就好。

博弈性质:如果当前状态对手怎么走都败,此状态就是胜,不然就是负。

记忆化搜索一下水过。


代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 30
#define M 10000
using namespace std;
int f[N][M],a[N],n,m;
// 1为败
int dfs(int x,int y)
{
	if(f[x][y]+1)return f[x][y];
	for(int i=max(0,y-a[x]);i<y;i++)// 枚举剩多少石子
		if(!dfs((x+1)%n,i))return f[x][y]=1;
	return f[x][y]=0;
}
int main()
{
//	freopen("test.in","r",stdin);
	while(scanf("%d",&n),n)
	{
		n<<=1,scanf("%d",&m);
		for(int i=0;i<n;i++)scanf("%d",&a[i]);
		memset(f,-1,sizeof(f));
		for(int i=0;i<n;i++)f[i][0]=1;
		if(dfs(0,m))puts("1");
		else puts("0");
	}
}



你可能感兴趣的:(动态规划,博弈,Nim,POJ2068)