1. 程式人生 > >博弈論 硬幣遊戲1

博弈論 硬幣遊戲1

Alice和Bob在玩這樣一個遊戲。給定k個數字a[1],a[2],…,a[k]。一開始,有x枚硬幣,Alice和Bob輪流取硬幣。每次所取硬幣的枚數一定要在a[1],a[2],…,a[k]當中。Alice先取,取走最後一枚硬幣的一方獲勝。當雙方都採取最優策略時,誰會獲勝?題目假定a[1],a[2],…,a[k]中一定有1。

限制條件:

 1<=x<=10000

 1<=k<=100

 1<=a[i]<=x

輸入:

 x=9

 k=2

 a={1,4}

輸出:

 Alice

思路:

按照我們常人的想法,當前狀態有三種狀態 必勝,必敗,或者不確定;當對了兩個聰明的人來說就只有兩種情況:必勝,必敗;下面請看必勝態,必敗態的解釋;

必敗態:有x枚硬幣,有a[0]~a[k-1]中取法,當前不管你按那種取法取,都在人家的掌控之中,都得按照人家的節奏來,因為人家和你都是一樣聰明;也就是說x-a[i] (0<=i<k)為必勝態(從x-a[i]取的人掌控著戰局),x就是必敗態;

必勝態:當前取的人,按照自己聰明的想法取,他取過之後能使得對方不管按那種方法取,都贏不了,也就是說對方不管按那種方法取,剩下的硬幣數,還是必勝態,也就是說只要自己一直按照聰明的想法取,不管對方多麼聰明都無計可施;

當前為x枚硬幣

當x==0時,為必敗態;

當x>0時

若對於某個i (0<=i<k且x-a[i]>=0)x-a[i] 為必敗態,那麼x是必勝態;

若對於任意的i(0<=i<k且x-a[i]>=0)x-a[i]為必勝態,那麼x就是必敗態;

寫程式,算是用了動態規劃的思想,從小到大推出是必勝態,還是必敗態;

程式碼:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define Max 10010
bool win[Max];
int main()
{
	int i,j,x,k;
	int a[110];
	while(~scanf("%d%d",&x,&k))
	{
		for(i=0;i<k;i++)
			scanf("%d",&a[i]);
		win[0] = false;
		for(j=1;j<=x;j++)
		{
			win[j] = false;    
			for(i=0;i<k;i++) 
			{
				if(j>=a[i])
				 	win[j] |= !win[j-a[i]]; //表述法一:當j>=a[i]時,只要有一個a[i],使得j-a[i]為必敗態,那麼j就為必勝態;
			 	//if(j>=a[i]&&!win[j-a[i]])   // 表述法二:和上面一樣; 
			 	//	win[j] = true;
				/*if(j>=a[i])        //表述法三: 
			 	{ 
			 		if(win[j-a[i]])
			 			continue;
			 		else break;
			 	}*/		
			}
			/*if(i>=k) win[j] = false;  // 取任意一種情況,剩下的都為必勝態,此時就為必敗態; 
			else win[j] = true;       // 只要有一種情況取後,剩下的為必敗態,那麼此時就是必勝態(一直按照自己聰明的想法取)
			*/
		}
		if(win[x]) printf("Alice\n");
		else printf("Bob\n");
	}
	return 0;
}