初識博弈【一】(挑戰程序)(poj2348,poj2484)

看了看《挑戰程序設計競賽》的4.2博弈方便的知識點。

感覺也真是聰明啊……

整理整理,鍛鍊大腦~


1】Alice和Bob在玩這樣一個遊戲:給定k個數字a1,a2…ak。一開始,有x個石子,Alice和Bob輪流取石子。每次所取石子的個數一定要在a1~ak中。Alice先取。取走最後一個石子的一方獲勝。當雙方都採取最優策略時,誰會獲勝?題目假定a1~ak中一定有1.


分析題目,有三種情況:

1.沒有剩餘,也就是只剩下了0個,那麼必敗

2.對於某個i(1<=i<=k),j-A[i]必敗那麼j就是必勝(可以從剩下的j中拿去A[i],達到對方的必敗狀態)

3.對於某個i(1<=i<=k),j-A[i]必勝那麼j就是必敗(對方可以從剩下的j中拿去A[i])


建立一個win[j]數組,表示輪到玩家拿的時候剩餘j時的勝負狀態。



#include <cstdio>
#define maxn 105

int X,K,A[maxn]; 
bool win[maxn];
void slove(){
	
	win[0]=false;
	for(int j=1;j<=X;j++){
		//如果對手達到必敗,那麼必勝
		win[j]=false;
		/*三種都可
		for(int i=0;i<K;i++){	//如果可取的A[i]<=剩餘的j,進入判斷 
			win[j] |= ( A[i]<=j  && !win[j-A[i]]);
		} 
		
		for(int i=0;i<K&&A[i]<=j;i++){
			win[j] |= !win[j-A[i]] ;
		} 		
		*/
		for(int i=0;i<K&&A[i]<=j;i++){
			if(!win[j-A[i]])
				win[j] |=true ;
		} 
	
	}
	if(win[X]) puts("Alice");
	else puts("Bob");
}
int main() {
	
	scanf("%d%d",&X,&K);
	for(int i=0;i<K;i++){
		scanf("%d",&A[i]);
	}
	slove();
	
	return 0; 
}





2】POJ2484

A Funny Game
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 4824   Accepted: 2997

Description

Alice and Bob decide to play a funny game. At the beginning of the game they pick n(1 <= n <= 106) coins in a circle, as Figure 1 shows. A move consists in removing one or two adjacent coins, leaving all other coins untouched. At least one coin must be removed. Players alternate moves with Alice starting. The player that removes the last coin wins. (The last player to move wins. If you can't move, you lose.) 
 
Figure 1

Note: For n > 3, we use c1, c2, ..., cn to denote the coins clockwise and if Alice remove c2, then c1 and c3 are NOT adjacent! (Because there is an empty place between c1 and c3.) 

Suppose that both Alice and Bob do their best in the game. 
You are to write a program to determine who will finally win the game.

Input

There are several test cases. Each test case has only one line, which contains a positive integer n (1 <= n <= 106). There are no blank lines between cases. A line with a single 0 terminates the input. 

Output

For each test case, if Alice win the game,output "Alice", otherwise output "Bob". 

Sample Input

1
2
3
0

Sample Output

Alice
Alice
Bob


n枚硬幣排成一個圈,

Alice和Bob輪流從中取1~2枚硬幣,取得2枚硬幣要相連,取走最後一枚硬幣獲勝。雙方採取最優策略,誰會獲勝?


如果兩個人取硬幣的的狀態一樣(中間不連續),則是一種必敗狀態。

A取硬幣,B取可以達到 和A同樣狀態的 硬幣,那麼B必勝。


所以,Alice在第一步取了1枚或者2枚硬幣之後,原本成圈的硬幣編程了長度爲n-1或者n-2的鏈,

只要B在中間位置根據奇偶性取走硬幣就可以把硬幣扽成長度相同的鏈。

然後A就必敗了…

當然除了N<=2的情況。

好吧,思維繞一點,但是想清楚了,代碼一下就出來…所以這種題考的實際就是智商…多做多看~…

#incldue <cstdio>

int main(){
	int n;
	scanf("%d",&n);
	if(n<+2) puts("Alice");
	else puts("Bob");
	return 0;
}




3.Poj2348

Euclid's Game
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 8594   Accepted: 3500

Description

Two players, Stan and Ollie, play, starting with two natural numbers. Stan, the first player, subtracts any positive multiple of the lesser of the two numbers from the greater of the two numbers, provided that the resulting number must be nonnegative. Then Ollie, the second player, does the same with the two resulting numbers, then Stan, etc., alternately, until one player is able to subtract a multiple of the lesser number from the greater to reach 0, and thereby wins. For example, the players may start with (25,7): 
         25 7

         11 7

          4 7

          4 3

          1 3

          1 0

an Stan wins.

Input

The input consists of a number of lines. Each line contains two positive integers giving the starting two numbers of the game. Stan always starts.

Output

For each line of input, output one line saying either Stan wins or Ollie wins assuming that both of them play perfectly. The last line of input contains two zeroes and should not be processed.

Sample Input

34 12
15 24
0 0

Sample Output

Stan wins
Ollie wins


輾轉相除博弈遊戲


預處理:

1.先調整使得a<b

2.若b%a==0 必勝

判斷:

1】.b-a<a:只有一種選擇,就是減去一個a。

若減去之後爲必勝,則自己必敗。

若減去之後爲必敗,則自己必勝。


2】.b-a>a:多種選擇,

假設x是使得b-x*a<a的整數,如果從b-(x-1)*a之後,也就達到了狀態1 。

2.1如果減去之後是必敗態:

則當前狀態是必勝態

----------

2.2如果減去之後是必勝態,此時可以減去a*x,這樣就達到了2.1所說的必勝態的下一個狀態,也就是必敗態

所以當前狀態是必勝態

---------

Eg:

(4,17)如果17-12=5也就是(4, 5)必敗,所以直接-12就能必勝

(4,19)如果19-12=7也就是(4,7),對方必勝,那麼直接減去16達到(4,7)對的下一個(4,3)必敗狀態給對手

也就扭轉了局面。達到必勝態

所以,從初始狀態開始,首先達到自由度的2狀態的一方獲勝。


注意這裏循環中每次的first狀態發生變化

因爲每種狀態都是互推的,這次的必勝,下次的必敗。

所以當遇到可以停止的時候break;



#include <cstdio>

void swap(int &x,int &y){
	int t;
	t=x,x=y,y=t; 
}
int main(){
	int a,b;
	while(scanf("%d%d",&a,&b)!=EOF){
		if(a==0&&b==0)	break;
		bool first=true;
		while(true){
			if(a>b) swap(a,b);
			//第一種情況,b是a的倍數。必勝。 
			if( b%a ==0 ) break;
			
			//第二種情況,必勝。 
			if( b-a > a ) break;
			
			b-=a;
			first=!first;	
		}
		if(first)	puts("Stan wins"); 
		else 	puts("Ollie wins");	
	}
	
	return 0;
}



















發佈了69 篇原創文章 · 獲贊 49 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章