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;
}
}
}
}