[Game Theory] A Preliminary Study (Bash, Wizov, Nim, Fibonacci)

Borrowing from the big guy's data:
game theory .

1. Bash Game

Citation, one of the oldest games:

A and B should report the number together. Each person should report at least one at a time and a maximum of four. It depends on who reports 30 first (the 30th number).

analysis

The first time the number is reported, the number of numbers reported by A is x, then the number of numbers reported by B is 5-x, and now the problem becomes the following:
A and B report together, see who reports the 25th first
and then The problem is gradually simplified and the scale is reduced: 20, 15, 10, 5. The last question is to see who reports to 5 first. At this time, no matter how A reports the number, B must report the last number, so B must win. From the analysis here, we can get:
As a back player, B will not lose in this game.

induction

If we want to report n numbers, at least 1 each time, and at most m numbers, we can find such an integer k and r such that n = k * (m+1) + r , and substituting it into the example shows that if r = 0, then the first move must be defeated, otherwise, the first move must be won (here I am not sure yet...).

Bash game (generalization)

Problem Description

There is only a pile of n items, and two people take turns from them. It is stipulated that at least one item is taken each time, and at most m items are taken. The winner is the one who takes the light.

Code example

#include<iostream>
using namespace std;
int main()
{
	int n, m;
	while (cin >> n >> m)
	{
		if (n % (m + 1) == 0)
		{
			cout << "后手必胜" << endl;//先手必败
		}
		else
		{
			cout << "先手必胜" << endl;
		}
	}
	return 0;
}

2. Wythoff Game

Problem Description

There are two piles of several items each. Two people take turns to take at least 1 item from one pile, at most no limit, or take the same item from both piles at the same time, and it is stipulated that the one who takes the last one wins.

Problem solving conclusion

If the initial value of the two piles of items is (x, y), and x <y, then let z = y-x;
set * w = (int)[((sqrt(5)+1)/2) z] ;
(The picture below is human words)
Insert picture description here
If w = x, the first move must be defeated, otherwise the second move must be defeated;

Code example

#include<iostream>
#include<math.h>
using namespace std;

int main()
{
	int n1, n2, temp;
	while (cin >> n1 >> n2)
	{
		if (n1 > n2) //保证 n1 <= n2
		{
			swap(n1, n2);
		}
		temp = floor((n2 - n1) * (sqrt(5.0) + 1) / 2.0);
		if (temp == n1)
		{
			cout << "后手必胜" << endl;
		}
		else
		{
			cout << "先手必胜" << endl;
		}
	}
	return 0;
}

Three, Nimm Game (Nimm Game)

Problem Description

There are any piles of items, and the number of items in each pile is arbitrary. Two people take turns to take items from it. Each time they can only take part or all of the items from one pile, at least 1 item is taken, and the last item is taken. Win.

Problem solving conclusion

XOR all the items in each pile. If the value obtained is 0, then the first move must be defeated (the second move must win), otherwise the first move must win.

Code example

#include<iostream>
#include<math.h>
using namespace std;
int main()
{
	int i, n, ans, temp;
	// n 堆物品
	while (cin >> n)
	{
		temp = 0;
		for ( i = 1; i <= n; i++)
		{
			cin >> ans;
			temp ^= ans; //我们把每一堆的物品数给异或起来
		}
		if (temp == 0)
		{
			cout << "后手必胜" << endl;
		}
		else
		{
			cout << "先手必胜" << endl;
		}
	}
	return 0;
}

Fourth, the Fibonacci game

Problem Description

There is a pile of items. Two people take turns to take items. The first hand takes at least one item, and there is no upper limit at most. However, the item cannot be taken out. After that, the number of items obtained each time cannot exceed twice the number of items taken last time and is at least one item. The person who walks the last item wins.

Problem solving conclusion

If and only if n is the Fibonacci number (n is the total number of items), the first move must be defeated.

Code example

#include<iostream>
#include<math.h>
using namespace std;
#define N 55
int f[N] = {}; //斐波那契数列

void Init();

int main()
{
	bool flag = false; // true : 先手必败,flase : 后手必败
	int n, i;
	Init();
	while (cin >> n)
	{
		if (n == 0)//不用玩了
		{
			break;
		}
		flag = false;
		for ( i = 0; i < N; i++) //判断是否是斐波那契数,只好一个一个试
		{
			if (n == f[i])
			{
				flag = true;//先手必败
				break;
			}
		}
		if (flag)
		{
			cout << "后手必胜" << endl;
		}
		else
		{
			cout << "先手必胜" << endl;
		}
	}
	return 0;
}

void Init()
{
	int i;
	f[0] = 1;
	f[1] = 1;
	for ( i = 2; i < N; i++)
	{
		f[i] = f[i - 1] + f[i - 2];
	}
}

to sum up

It can be noted that all the above game problems
1. The winning condition is to get the last item;
2. If the result meets the corresponding condition, the first move must be defeated;

Guess you like

Origin blog.csdn.net/weixin_44092088/article/details/110305734