一個簡單的博弈問題 取球問題

/*   ios

今盒子裏有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 編程

*/ spa

//思路以下 code

/* 遞歸

若是咱們從 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 個球時,就是咱們要求得結果。
這就是動態規劃過程,先將大問題劃分紅子問題,再從子問題開始着手,先解出子問題的解,從子問題解出發,
逐步加大問題,倒着追根溯源,找到咱們要求解的問題爲止。

注意:實際上動態規劃時都是先能構造原問題與子問題之間的遞歸方程,按照遞歸方程列算法 it

*/ io



//代碼以下,以模仿動態規劃方式解答 class

/* 
	文件名稱: 取球
	建立日期: 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;
}
相關文章
相關標籤/搜索