初始博弈【二】Nim(hdu 1849,poj1704)

Nim                                                           


有n堆石子,每堆有ai顆石子,Alice和Bob輪流從非空的石子堆中取走至少一顆石子。Alice先取,去逛所有石子的一方獲勝。當雙方都採取最優策略時,誰會獲勝?

1<=n<=1^6

1<=ai<=10^9


INPUT:

3

1 2 4


OUTPUT:

Alice



注意這個結論成立:

a1 XOR a2 XOR a3 XOR ……XOR an ≠ 0  ==> 必勝態

a1 XOR a2 XOR a3 XOR ……XOR an = 0  ==> 必敗態

 

所以呢,非0則Alice獲勝,爲0則Bob獲勝



《挑戰程序》上的證明如下:

一旦從XOR爲0的狀態取走至少一顆石子,XOR就一定會變成非0。因此,可以證實必敗之後肯定是必勝。

--------------------

觀察XOR的二進制表示最高位的1,選取石子數的二進制表示對應位也爲1的某堆石子。

只要從中取走使得該位變爲0,且其餘XOR中的1也反轉的數量的石子,XOR就可以變成0。


同時,看了看這幾篇博文感覺更加詳細

http://blog.csdn.net/lgdblue/article/details/15809893

http://blog.csdn.net/acm_cxlove/article/details/7854530

第一個博客中的例子就很好理解^_^


核心代碼:

int N;

void solve(){
	int x=0;
	for(int i=0;i<N;i++) x^A[i];
	
	if(x!=0) puts("Alice");
	else puts("Bob");
}



hduoj1849

Rabbit and Grass

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3350    Accepted Submission(s): 2496


Problem Description
大學時光是浪漫的,女生是浪漫的,聖誕更是浪漫的,但是Rabbit和Grass這兩個大學女生在今年的聖誕節卻表現得一點都不浪漫:不去逛商場,不去逛公園,不去和AC男約會,兩個人竟然貓在寢食下棋……
說是下棋,其實只是一個簡單的小遊戲而已,遊戲的規則是這樣的:
1、棋盤包含1*n個方格,方格從左到右分別編號爲0,1,2,…,n-1;
2、m個棋子放在棋盤的方格上,方格可以爲空,也可以放多於一個的棋子;
3、雙方輪流走棋;
4、每一步可以選擇任意一個棋子向左移動到任意的位置(可以多個棋子位於同一個方格),當然,任何棋子不能超出棋盤邊界;
5、如果所有的棋子都位於最左邊(即編號爲0的位置),則遊戲結束,並且規定最後走棋的一方爲勝者。

對於本題,你不需要考慮n的大小(我們可以假設在初始狀態,棋子總是位於棋盤的適當位置)。下面的示意圖即爲一個1*15的棋盤,共有6個棋子,其中,編號8的位置有兩個棋子。



大家知道,雖然偶爾不夠浪漫,但是Rabbit和Grass都是冰雪聰明的女生,如果每次都是Rabbit先走棋,請輸出最後的結果。
 

Input
輸入數據包含多組測試用例,每個測試用例佔二行,首先一行包含一個整數m(0<=m<=1000),表示本測試用例的棋子數目,緊跟着的一行包含m個整數Ki(i=1…m; 0<=Ki<=1000),分別表示m個棋子初始的位置,m=0則結束輸入。
 

Output
如果Rabbit能贏的話,請輸出“Rabbit Win!”,否則請輸出“Grass Win!”,每個實例的輸出佔一行。
 

Sample Input
2 3 5 3 3 5 6 0
 

Sample Output
Rabbit Win! Grass Win!
 




#include <cstdio>

int main(){
	int n;
	
	while(scanf("%d",&n)!=EOF){
		if(n==0) break;
		int ans=0,x;
		for(int i=0;i<n;i++){
			scanf("%d",&x);
			ans^=x;
		}
		if(ans==0) puts("Grass Win!");
		else puts("Rabbit Win!");
	}

	return 0;
}






POJ1704

Georgia and Bob
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 9007   Accepted: 2899

Description

Georgia and Bob decide to play a self-invented game. They draw a row of grids on paper, number the grids from left to right by 1, 2, 3, ..., and place N chessmen on different grids, as shown in the following figure for example: 

Georgia and Bob move the chessmen in turn. Every time a player will choose a chessman, and move it to the left without going over any other chessmen or across the left edge. The player can freely choose number of steps the chessman moves, with the constraint that the chessman must be moved at least ONE step and one grid can at most contains ONE single chessman. The player who cannot make a move loses the game. 

Georgia always plays first since "Lady first". Suppose that Georgia and Bob both do their best in the game, i.e., if one of them knows a way to win the game, he or she will be able to carry it out. 

Given the initial positions of the n chessmen, can you predict who will finally win the game? 

Input

The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. Each test case contains two lines. The first line consists of one integer N (1 <= N <= 1000), indicating the number of chessmen. The second line contains N different integers P1, P2 ... Pn (1 <= Pi <= 10000), which are the initial positions of the n chessmen.

Output

For each test case, prints a single line, "Georgia will win", if Georgia will win the game; "Bob will win", if Bob will win the game; otherwise 'Not sure'.

Sample Input

2
3
1 2 3
8
1 5 6 7 9 12 14 17

Sample Output

Bob will win
Georgia will win


棋盤遊戲~

將棋子兩兩整體考慮,然後就可以轉化成Nim啦~

【1】如果爲偶數個棋子的話:兩兩之間的間隔作爲每堆石子的個數。

          將倆個裏面右邊的棋子左移->取石子。

          將倆個裏面左邊的棋子左移.距離變大,石子增多,這裏不同於Nim,但是再將右邊的棋子左移就又變成Nim了,所以也不影響~

          這樣呢,所有的棋子之間的間隔變成0也就是取完了石子,達到必勝態。

          間隔爲0-->不管前面的棋子怎麼動,只要挪動跟他成對的後面的那個棋子到相鄰位置就好了。

---------------

【2】如果爲奇數個棋子。設置一個座標爲0的就好了~

#include <cstdio>
#include <algorithm>
#define maxn 10005
using namespace std;
int P[maxn],n;

void solve(){
	if(n%2!=0){	//奇數 
		P[n++]=0;
	}	
	sort(P,P+n);
	int ans=0;
	for(int i=1;i<n;i+=2){
		ans^=(P[i]-P[i-1]-1); 
	}
	if(ans==0) puts("Bob will win");
	else puts("Georgia will win");
	
} 

int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		for(int i=0;i<n;i++){
			scanf("%d",&P[i]);
		}
		solve();
	
			
	}
	return 0;
} 







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