一个简单的博弈问题 取球问题

/*  

今盒子里有n个小球,A、B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,也可以看到盒中还剩下多少个,并且两人都很聪明,不会做出错误的判断。

    我们约定:
    
    每个人从盒子中取出的球的数目必须是:1,3,7或者8个。
    轮到某一方取球时不能弃权!
    A先取球,然后双方交替取球,直到取完。
    被迫拿到最后一个球的一方为负方(输方)
    请编程确定出在双方都不判断失误的情况下,对于特定的初始球数,A是否能赢?
    程序运行时,从标准输入获得数据,其格式如下:
    先是一个整数n(n<100),表示接下来有n个整数。然后是n个整数,每个占一行(整数<10000),表示初始球数。

    程序则输出n行,表示A的输赢情况(输为0,赢为1)。

    例如,用户输入:



10
18

    则程序应该输出:
0
1
1

0

*/

//思路如下

/*

如果我们从 10000 个球开始的话,有点困难,我们不清楚怎么取球能赢,我们想列举出所有可能情况,但这个几乎不可能。因为情况太多,数量应该是指数级别的。

//----都是假定A先取球, 
我们降低难度,从最简单的子问题开始,我们设想 : 

<1> 当只有 1 个球时,A只有 1 种取法( 1 ) 如果 A 先取球,不管 A 怎么取,A都必输。
    ==> 记下这个经验 --> 1 个球时,先取必输


<2> 当有 2 个球时, A只有 1 种取法( 1 ), A当前只能取 1 个球,B输了
    ==> 记下这个经验 --> 2 个球时, 先取必赢


<3> 当有 3 个球时, A有 2 种取法(1,3), A就会想 我如果取 1 个球,此时还剩 2 个球,
    那么根据前两次经验中第二个经验,"只有两个球时,先取必赢", 所以我不能取 1 个球, 
    我如果取 3 个球,那么我又输了。
    ==> 记下这个经验 --> 3 个球时, 先取必输

<4> 当有 4 个球时, A有 2 种取法(1, 3), 同样A又会想,我如果取 1 个球,此时还剩 3 个球,
    那么根据前三次经验中第三个经验, "先取必输",所以我就取 1 个球即可赢得比赛。
   ==> 记下这个经验 -->  4 个球时, 先取必赢  

<5> 当有 5 个球时。。。。。
  。
  。
  。
  。
  。

<n> 当有 n 个球时 。。。。。

通过不断迭代,得到这个第 n 个球时,就是我们要求得结果。
这就是动态规划过程,先将大问题划分成子问题,再从子问题开始着手,先解出子问题的解,从子问题解出发,
逐步加大问题,倒着追根溯源,找到我们要求解的问题为止。

注意:实际上动态规划时都是先能构造原问题与子问题之间的递归方程,按照递归方程列算法

*/



//代码如下,以模仿动态规划方式解答

/* 
	文件名称: 取球
	创建日期: 2013/3/11
*/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const a[4] = {1, 3, 7, 8};

bool	serach1(vector<bool> v, int n)
{
	int i;
	for (i = 0; i < 4; i++)
	{
		int k = n - a[i];
		if (k == 0)
			return false;
		if (v[k] == false)
			return true;
	}
	return false;
}

void	show(vector<bool> v)
{
	vector<bool>::iterator it;
	int k = 0;
	for (it = v.begin() + 1; it != v.end(); it++)
	{
		++k;
		cout << k << "\t" << *it << "\n";
	}
	cout << endl;
}

int	main()
{

	vector<bool> v;
	v.push_back(0);//废除

	v.push_back(0);//1
	v.push_back(1);
	v.push_back(0);//3
	
	int i = 0;

	for (i = 4; i < 100; i++)
	{
		v.push_back(serach1(v, i));
	}
	return 0;
}


你可能感兴趣的:(简单的博弈,取球问题)