vijos1196(博弈论)

桌子上放着两堆糖果,Matrix67和Shadow轮流对这些糖果进行操作。在每一次操作中,操作者需要吃掉其中一堆糖果,并且把另一堆糖果分成两堆(可以不相等)留给对方操作。游戏如此进行下去,糖果数会越来越少,最后必将出现这样一种情况:某人吃掉一堆糖果后发现另一堆里只剩一块糖果不能再分了。游戏规定此时该操作者吃掉最后这一块糖果从而取胜。

这个游戏是不公平的。对于任意一种初始状态,总有一方有必胜策略。所谓有必胜策略是指,无论对方如何操作,自己总有办法取胜。

Matrix67和Shadow将进行10次游戏,每一次游戏中总是Matrix67先进行操作。Matrix67想知道每一次游戏中谁有必胜策略。

 

 

直接分析,真是不好做,分析化找规律感觉挖掘的性质不够多,分析的不够全。

但是发现这题可以打表出来,以此找规律!

 

打表实际上就是暴力喽,f【i】表示分大小为i的堆,先手是否有必胜策略。经过分析发现f【i】是从f【1~i/2】推过来的。

那么博弈论dp搞一搞,70分就有了。以下有注意点。

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;

int n,m;
bool f[12005];
void init()
{
	f[1]=true;
	for (int i=2;i<=10000;i++)
	{
		for (int j=1;j<=i/2;j++)//枚举它分成的所有情况,在所有情况中选对于当前先手的最优,这也就是博弈论dp的思路。
		{
			int x=j,y=i-j;
			f[i]=f[i]||(!(f[x]||f[y]));//这里的“非”必须是!号,~号是不行的!!!!!!
		}
	}
}
int main()
{
	init();
	for (int i=1;i<=200;i++) printf("%d %d\n",i,f[i]);
	while (scanf("%d%d",&n,&m)!=EOF)
	{
		if (f[n]||f[m]) printf("Matrix67\n");else printf("Shadow\n");
	}
	return 0;
} 

 

打出f【i】的表,发现。。。五个为一循环,不用dp了,o(1)直接算就行
1   1
2   0
3   0
4   1
5   1
6   1

7   0
8   0
9   1
10 1
11 1
12 0
13 0
14 1
15 1
16 1
17 0
18 0
19 1
20 1
21 1
22 0
23 0

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;

bool f(int n)
{
	n=n%5;
	switch(n)
	{
		case 0:
		case 1:
		case 4:return true;
		case 2:
		case 3:return false;	
	}
}
char s1[10005],s2[10005];
int len1,len2;
int main()
{
	while (scanf("%s%s",s1,s2)!=EOF)
	{
		len1=strlen(s1);len2=strlen(s2); 
		if (f(s1[len1-1]-'0')||f(s2[len2-1]-'0')) printf("Matrix67\n");else printf("Shadow\n");
	}
	return 0;
} 

总结

1:博弈论问题(这里适合nim游戏)的主体思路

      一 :主要思路就是从小范围情况向大范围情况推,由此进行归纳和总结

      二:分情况手推小范围的数据,模拟nim游戏的运行,在计算的过程中感受后来状态和之前状态之间的关系。

      三:有些题看着数据范围过大(此题的数达到10000位),可能最终答案可以从输入的这些数据本身找答案,不必想像弈论dp从前忘后推了,实际上这就是要我们找规律

2:这题规律,真心不好推,直接找规律不行,分析题目性质找规律也很难,怎么办?

写暴力,输出答案找规律。考场上也是要这样,写暴力程序找规律(这里是用博弈论dp写了70分的数据,10000的数据就是给这种做法的)。

3:博弈论dp才是更通用的做法,找规律只是对这种做法的优化而已(感觉很多给数据70分和100分的两种,70分就是好不容易想到的主要想法,而100分就是对这个算法的优化),博弈论dp从小往大推,一定要保证先后手都是最优策略,当前=(所有情况的最差策略(保证后手最优策略))中的最优策略(保证先手最优策略)。//只可意会不可言传,蓝书67页”sum游戏“的做法可将这个思想进行很好的概括,这题很便于意会了!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值