博弈

1. 威佐夫博弈

裸题如下

取石子
题目内容:

有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中
取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数
目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。
输入描述
输入包含若干行,表示若干种石子的初始情况,其中每一行包含两个非负整数a和b,表示两堆石子的数目,a和b都不大于
1,000,000,000。

输出描述

输出对应也有若干行,每行包含一个数字1或0,如果最后你是胜者,则为1,反之,则为0。

输入样例

2 1
8 4
4 7

输出样例

0
1
0

0.618是黄金分割率。而威佐夫博弈正好是1.618,1.618 = (sqrt(5.0) + 1) / 2, 这个式子很准, 记代码吧, 解释是看不懂的, 即a 为两数中小数, b为大数, a, b之差与1.618相乘, 若为a则必败, 否则必胜


#include<iostream>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;

int main()
{
	int a, b;
	double r, c;
	while (cin >> a >> b)
	{
		if (a > b)
			swap(a, b);
		r = (sqrt(5) + 1) / 2;
		c = b - a;
		int temp = c * r;
		if (temp == a) cout << "0" << endl;
		else cout << "1" << endl;
	}
}

1. 普通的取石子问题

取石头
题目内容:

有甲乙两个人玩取石子游戏,共有n个石子(1<=n<=30000)两个人轮流取,甲先取.每次最多取m个(1<=m<=30000)最少取一个,
当轮到谁取的时候没有石子了,谁就赢.比如4个石子,每次最多取3个,那末先取的人(甲)一定赢
(例如,甲拿走3个,乙只能拿走1个,下面轮到甲没有石子了,甲赢了.)
现在要求你写一个程序,输入n(总的石子个数),最多可以取的石子个数m,输出甲(先取的人)是否会赢,会赢的话输出YES,
否则输出LOSE.
我们这里假设甲乙两个人都采取最好的策略,也就是甲乙都非常想赢而且足够聪明.
比如输入11 4 输出"LOSE"

输入描述

整数n m, 空格隔开

输出描述

YES或者LOSE

输入样例

11 4

输出样例

LOSE
递推


#include<iostream>
#include<cmath>
#include<vector>
#include<string>
#include <stdio.h>
#include<algorithm>
#include<functional>
using namespace std;
typedef long long ll;

bool win[100000];

int main()
{
	int n, m;
	cin >> n >> m;
	win[0] = 1;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
			win[i] |= i >= j && !win[i - j];
	}

	if (win[n])
		cout << "YES";
	else
		cout << "LOSE";
}

3. Nim博弈

题目内容:

有n堆石子, 每堆ai个石子, Alice和Bob轮流从非空的堆中取出至少一颗石子, Alice先取, 取光者获胜,当双方取最佳策略时, 谁会获胜?
对于每一个状态来说(必胜态或者必败态), 当取走至少一颗石子后, 状态必然变为相反, 由此可以用异或来做

int n, a[max_n];
void solve()
{
	int x = 0;
	for (int i = 0; i < n; i++)
		x ^= a[i];
	if (x != 0)
		puts("Alice");
	else
		puts("Bob");
}

4. Nim博弈变型

博弈- 取石头
题目内容:

m堆石子,甲乙两人轮流取,每次需先选择1堆,并取任意数目的石子. 最后取完者的获胜.
规定甲先取。
输入描述
可能有多组测试数据。每组的第一行是m, 第二行是m个整数,表示每堆石子的数目。

输出描述

每个测试用例,甲失败则输出“No”。
否则输出"Yes", 并在下面的行输出取法。
按堆号顺序输出各种甲能取胜的首次取法a,b,表示在第a堆石子中取完石子后剩下b个,甲可以获胜。

输入样例

2
45 45
3
3 6 9
5
5 7 8 9 10

输出样例

No
Yes
9 5
Yes
8 1
9 0
10 3


#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<vector>
#include<stack>
using namespace std;
typedef long long ll;

int a[10000];

int main()
{
	int n;
	while (cin >> n)
	{
		int x = 0;
		for (int i = 1; i <= n; i++)
			cin >> a[i], x ^= a[i];
		if (!x)
			cout << "No" << endl;
		else
		{
			cout << "Yes" << endl;
			for (int i = 1; i <= n; i++)
			{
				int ans = a[i] ^ x;			//剩余石子数
				if(ans <= a[i])				//剩余石子数要小于等于a[i]
				cout << a[i] << " " << ans << endl;
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值