Day14(博弈论入门)

博弈论,即公平组合游戏,满足下列一些特征:

  • 一场游戏有两个玩家,两个玩家轮流行动,是经典的回合制游戏。
  • 两个玩家的移动按照规则移动,并且两玩家之间的移动不区分身份。
  • 两个玩家按照最优的决策行动,即给定一个局势,能够一开始就区分出先手必胜还是先手必败。
巴什博奕

Brave Game

十年前读大学的时候,中国每年都要从国外引进一些电影大片,其中有一部电影就叫《勇敢者的游戏》(英文名称:Zathura),一直到现在,我依然对于电影中的部分电脑特技印象深刻。
今天,大家选择上机考试,就是一种勇敢(brave)的选择;这个短学期,我们讲的是博弈(game)专题;所以,大家现在玩的也是“勇敢者的游戏”,这也是我命名这个题目的原因。
当然,除了“勇敢”,我还希望看到“诚信”,无论考试成绩如何,希望看到的都是一个真实的结果,我也相信大家一定能做到的~
各位勇敢者要玩的第一个游戏是什么呢?很简单,它是这样定义的:
1、 本游戏是一个二人游戏;
2、 有一堆石子一共有n个;
3、 两人轮流进行;
4、 每走一步可以取走1…m个石子;
5、 最先取光石子的一方为胜;
如果游戏的双方使用的都是最优策略,请输出哪个人能赢。

Input

输入数据首先包含一个正整数C(C<=100),表示有C组测试数据。
每组测试数据占一行,包含两个整数n和m(1<=n,m<=1000),n和m的含义见题目描述。

Output

如果先走的人能赢,请输出“first”,否则请输出“second”,每个实例的输出占一行。

在该例题中,每次可以取1~m个石子,现在先假设能够取 颗石子,画出的关系图如下:

石子012345678910
状态PNNNPNNNPNN

NP关系推理的题目基本上都是通过找规律来解题。在本题中,显然当n%(m+1)==0的时候是P点,其余情况则是N点。

#include <bits/stdc++.h>

using namespace std;

int t,n,m;

int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		if(n<=m) cout<<"first"<<endl;
		else n%(m+1)==0?cout<<"second"<<endl:cout<<"first"<<endl;
	}
}
尼姆博奕

Being a Good Boy in Spring Festival

一年在外 父母时刻牵挂
春节回家 你能做几天好孩子吗
寒假里尝试做做下面的事情吧
陪妈妈逛一次菜场
悄悄给爸爸买个小礼物
主动地 强烈地 要求洗一次碗
某一天早起 给爸妈用心地做回早餐
如果愿意 你还可以和爸妈说
咱们玩个小游戏吧 ACM课上学的呢~
下面是一个二人小游戏:桌子上有M堆扑克牌;每堆牌的数量分别为Ni(i=1…M);两人轮流进行;每走一步可以任意选择一堆并取走其中的任意张牌;桌子上的扑克全部取光,则游戏结束;最后一次取牌的人为胜者。
现在我们不想研究到底先手为胜还是为负,我只想问大家:
——“先手的人如果想赢,第一步有几种选择呢?”

Input

输入数据包含多个测试用例,每个测试用例占2行,首先一行包含一个整数M(1<M<=100),表示扑克牌的堆数,紧接着一行包含M个整数Ni(1<=Ni<=1000000,i=1…M),分别表示M堆扑克的数量。M为0则表示输入数据的结束。

Output

如果先手的人能赢,请输出他第一步可行的方案数,否则请输出0,每个实例的输出占一行。

#include <bits/stdc++.h>

using namespace std;


int a[105],b[105];
int t,n,m,sum,out;

int main()
{
	while(~scanf("%d",&n))
	{
		if(n==0) return 0;
		sum=0;out=0;
		for(int i=0;i<n;i++)
		{
			scanf("%d",&a[i]);
			sum^=a[i];
		}
		for(int i=0;i<n;i++) if(a[i]>(sum^a[i])) out++;
		cout<<out<<endl;
	}
}
阶梯博弈

阶梯的序号如图所示,地面表示第0号阶梯。每次都可以将一个阶梯上的石子向其左侧移动任意个石子,没有可以移动的空间时(及所有石子都位于地面时)输。

假设我们是先手。我们按照尼姆博弈的原则进行第一次移动。如果对方移动奇数号阶梯的石子,我们继续按照尼姆博弈的原则移动。如果对方移动的是偶数号阶梯的石子,及对方将偶数号阶梯的石子移动到了奇数号(对奇数号产生了影响)我们就接着将对方移动到奇数号的石子再向下移动一个台阶,移动到偶数号。这就意味着在偶数号的棋子对我们的博弈是没有影响的。

Crazy Calendar—LightOJ - 1393

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[105];
int main() {
	int T, cas = 0; scanf("%d", &T);
	while (T--) {
		int n, m; scanf("%d %d", &n, &m);
		ll ans = 0;
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= m; ++j) {
				int t; scanf("%d", &t);
				if (((n + m) - (i + j)) % 2 == 1) ans ^= t;
			}
		}
		printf("Case %d: ", ++cas);
		if (ans) puts("win");
		else puts("lose");
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值