POJ Cutting Game(Nim博弈+grundy数)

Description

Urej loves to play various types of dull games. He usually asks other people to play with him. He says that playing those games can show his extraordinary wit. Recently Urej takes a great interest in a new game, and Erif Nezorf becomes the victim. To get away
from suffering playing such a dull game, Erif Nezorf requests your help. The game uses a rectangular paper that consists of W*H grids. Two players cut the paper into two pieces of rectangular sections in turn. In each turn the player can cut either horizontally
or vertically, keeping every grids unbroken. After N turns the paper will be broken into N+1 pieces, and in the later turn the players can choose any piece to cut. If one player cuts out a piece of paper with a single grid, he wins the game. If these two people
are both quite clear, you should write a problem to tell whether the one who cut first can win or not.

Input

The input contains multiple test cases. Each test case contains only two integers W and H (2 <= W, H <= 200) in one line, which are the width and height of the original paper.

Output

For each test case, only one line should be printed. If the one who cut first can win the game, print "WIN", otherwise, print "LOSE".

Sample Input

2 2

3 2

4 2

Sample Output

LOSE

LOSE

WIN

大致题意:题目的大概意思是这样的,就是说给你一个网格纸,大小w*h,让你剪,一人剪一次;随着一次次的剪,纸的数量越来越多,但大小越来越小,谁先剪出1*1的纸张谁就赢。这边其实是Nim博弈的变形,是的你没有看错,就是尼姆博弈的变形,不过就是变得有点大了,变得面目全非了。

何为Nim博弈,大牛见笑了,说给刚接触算法的同学听,所谓的尼姆博弈就是给你n堆石子,数量为a1, a2, a3,...an你从任意一堆里选择任意个,谁没得取谁就输。这一个是经典的题了,直接给结论,当满足a1^a2^a3^..an==0你就输了。就是每一堆的石子数的总亦或值为0的话就是输了。

回到问题上来,如何跟Nim博弈等价起来呢?这边起先只有一张纸,就是相当于只有一堆石子。这边引入一个grundy数的概念,我们现在只以一堆石子为例,其实这边可以说是状态的转移,一堆x个石子,一次可以转化为x-1,x-2, x-3..3, 2, 1.所以grundy值在这边就隐含的表示一张纸对应的石子数,一张纸可以经过剪变成两张纸,这两张纸也对应的各自的grundy数,这是就是一堆石子现在居然变成两堆了。但目前这个状态其实只要取这两个数亦或值又变成一堆。相当于Nim博弈两堆石子亦或可以只当成一堆。

接下来是关键怎么计算grundy数。一个状态的grundy数其实就是他能转移到的状态的grundy值除外的最小非负整数。为什么是这样的呢?首先Nim堆中石子x可以转化为x-1, x-2, x-3, ..2, 1.设当前的状态grundy数为y,那么他一定样要可以转化成y-1, y-2, ...3, 2, 1。举几个例子,比如当前状态可以转化成grundy数为1, 2, 3的状态,那么当前状态grundy数一定是4,这样才能转化为最小的。如果为3 ,5那么当前只能是0。就是说白了就是一个数,比这个数小的数他都能通过变化得到。可能有的人会有疑问,比如可以转化为3,
5的grundy值只能为0,但这个0其实可以变成3或5,这不就说明石子数量会增多吗?其实不然,这个时候先手将grundy值变大了,后手一定可以恢复原来的值,为什么呢?因为每一个grundy数根据他的求法可得一定是可以变为比他小的任意数,这不就说明石子数从变多又可以恢复原样了。

把输入的w*h只当做一堆石子来处理对应的grundy值为0时,就意味着输了。

AC代码:

# include <cstdio>
# include <cstring>
# include <set>
using namespace std;
int grundy[210][210];
int main(){
	int w, h, i, j, k, temp;
	for(i=2; i<=200; i++){
		for(j=2; j<=200; j++){
			int vis[1005];
			memset(vis, 0, sizeof(vis));
			//当出现w==1或h==1是就以为你输了就没得转移了
			for(k=2; i-k>=2; k++){//枚举可以转移到的转态
				vis[grundy[k][j]^grundy[i-k][j]]=1;
			}
			for(k=2; j-k>=2; k++){//枚举可以转移到的转态
			    vis[grundy[i][k]^grundy[i][j-k]]=1;
			}
			grundy[i][j]=0;
			for(k=0; ;k++)
        	if(vis[k]==0){//计算对应的grundy数
        		grundy[i][j]=k;
        		break;
			}
		}
	}
	while(scanf("%d%d", &w, &h)!=EOF){
		if(grundy[w][h])
		printf("WIN\n");
		else
		printf("LOSE\n");
	}
	return 0;
}
时间: 2024-08-28 23:20:10

POJ Cutting Game(Nim博弈+grundy数)的相关文章

poj 2960 S-Nim nim博弈grundy值计算法入门

题意: 给k堆石子,两人轮流向某一堆中拿,拿的个数要从给定的一个集合中取,没石子拿的输,问先手必胜还是必败. 分析: grundy值计算法的入门题. 代码: //poj 2960 //sep9 #include <iostream> #include <set> using namespace std; int s[128]; int grundy[10024]; int maxx; int num; int get_grundy(int x) { if(grundy[x]!=-1

POJ 2234 Matches Game(Nim博弈裸题)

Description Here is a simple game. In this game, there are several piles of matches and two players. The two player play in turn. In each turn, one can choose a pile and take away arbitrary number of matches from the pile (Of course the number of mat

ACM学习历程—HDU 3915 Game(Nim博弈 &amp;&amp; xor高斯消元)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3915 题目大意是给了n个堆,然后去掉一些堆,使得先手变成必败局势. 首先这是个Nim博弈,必败局势是所有xor和为0. 那么自然变成了n个数里面取出一些数,使得xor和为0,求取法数. 首先由xor高斯消元得到一组向量基,但是这些向量基是无法表示0的. 所以要表示0,必须有若干0来表示,所以n-row就是消元结束后0的个数,那么2^(n-row)就是能组成0的种数. 对n==row特判一下. 代码:

HDU 1907 Nim博弈变形

1.HDU 1907 2.题意:n堆糖,两人轮流,每次从任意一堆中至少取一个,最后取光者输. 3.总结:有点变形的Nim,还是不太明白,盗用一下学长的分析吧 传送门 分析:经典的Nim博弈的一点变形.设糖果数为1的叫孤独堆,糖果数大于1的叫充裕堆,设状态S0:a1^a2^..an!=0&&充裕堆=0,则先手必败(奇数个为1的堆,先手必败).S1:充裕堆=1,则先手必胜(若剩下的n-1个孤独堆个数为奇数个,那么将那个充裕堆全部拿掉,否则将那个充裕堆拿得只剩一个,这样的话先手必胜).T0:a1

[Nim博弈]hdu 1850 Being a Good Boy in Spring Festival

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1850 Being a Good Boy in Spring Festival Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4053    Accepted Submission(s): 2394 Problem Description

hdu1850 Being a Good Boy in Spring Festival(nim博弈)

Being a Good Boy in Spring Festival Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6682    Accepted Submission(s): 4039 Problem Description 一年在外 父母时刻牵挂 春节回家 你能做几天好孩子吗 寒假里尝试做做下面的事情吧 陪妈妈逛一次菜场 悄悄

hdu 1907(Nim博弈)

John Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 4407    Accepted Submission(s): 2520 Problem Description Little John is playing very funny game with his younger brother. There is one big bo

博弈-Nim博弈

Nim博弈-属于组合游戏 条件: 1.有两名选手: 2.两名选手交替对游戏进行移动(move),每次一步,选手可以在(一般而言)有限的合法移动集合中任选一种进行移动: 3.对于游戏的任何一种可能的局面,合法的移动集合只取决于这个局面本身,不取决于轮到哪名选手操作.以前的任何操作.骰子的点数或者其它什么因素: 4.如果轮到某名选手移动,且这个局面的合法的移动集合为空(也就是说此时无法进行移动),则这名选手负.根据这个定义,很多日常的游戏并非ICG.例如象棋就不满足条件3,因为红方只能移动红子,黑方

HDU 1850 Being a Good Boy in Spring Festival (Nim博弈)

#include <iostream> #include <algorithm> #define ss(a) scanf("%d",&a) #define ss64(a) scanf("%I64d",&a) using namespace std; int main() { int a[100],i,n,m,sum,cnt,j; while(~ss(n),n) { cnt=0; for (i=0,sum=0;i<n;i+