UVA 10404 Bachet's Game

大意不再赘述。

思路:我思考了好久,最终还是没想出来,去网上搜了搜解题报告,发现大多是似是而非的观点,于是把自己的想法写出来。

我们把Stan取石子记为0,Ollie取记为1。以第一组测试数据为例: 20 3 1 3 8

如果Stan想赢,则20的标记应该是0,我们以f[20] = 0,表示Stan取的第20颗石子,依次类推。

那么20的前态:19 17 15,则三个数之间必须有一个f值为1才可以,因为只要f[19] || f[17] || f[15] = 1,那么f[20]就可以等于0,因为题目满足最优子结构,而且Ollie取过其中的一个,Stan一定会取第20个石子,那么Stan wins,反之,Ollie wins,其他的子状态依次类推,最后我们最后只要判断f[n]是否为0即可。

另外:把a数组赋值为1,题目如果是Ollie先取呢?由于两者的状态相同,我们把输出改一下即可。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;

int stone[11];
int a[1000100];

int n, m;

char sw[20] = "Stan wins\n";
char ow[20] = "Ollie wins\n";

void init()
{
	memset(a, 1, sizeof(a));
}

void dp()
{
	for(int i = 0; i <= n; i++)
	{
		for(int j = 1; j <= m; j++)
		{
			if(a[i])
			{
				a[i+stone[j]] = 0;
			}
		}
	}
	if(a[n] == 0) printf("%s", sw);
	else printf("%s", ow);
}

void read_case()
{
	init();
	scanf("%d", &m);
	for(int i = 1; i <= m; i++)
	{
		scanf("%d", &stone[i]);
	}
}

void solve()
{
	read_case();
	dp();
}

int main()
{
	while(~scanf("%d", &n))
	{
		solve();
	}
	return 0;
}


 

你可能感兴趣的:(UVA 10404 Bachet's Game)