54 博弈转换

Cutting Game

POJ - 2311

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

一般情况而言,博弈都是最后走完的人赢得了比赛,但是,有些时候是相反的就是先完成了某一件事情后就先胜利了,问一下在某一种情形下,这个先手是否是有必胜的策略,这个会后我们可以这样想因为谁也不想给对手带来那种只有一行或是一列的状态,如果是有一行或是一列的话那么,现在面对的这个人就有必胜的策略,所以我们可以谁把最后的一步走了的话,就可以看作是谁赢了,这里的最后一步是下一步就必须是产生一行或是一列的情况,那么我们就可以把(2,2)(2,3)(3,2)看作是sg为0的状态就可以,所有的石子都在这三个点,

   aaa  
     
aaa    
     
     

对于这个表格的话,如果我们按照列给切开的话,我们肯定会选择的是第三列格子的两条边,因为只有这样的话,我们才不会给对方产生一列,同理行也是一样,我们可定会选第三行的两条边,这样我们就不会给对方产生一行,这样的话,我们就知道了,不论是按行,还是按列的来切割我们都会在距离边界是大于等于2的分界线上给切割;

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long ll;
const int Max = 500;

int sg[Max][Max];
int getsg(int n,int m){
    if(n<=0||m<=0)  return 0;
    if(sg[n][m]!=-1) return sg[n][m];
    bool visited[Max];
    memset(visited,0,sizeof(visited));
    for(int i=2;n-i>=2;i++){
        visited[(getsg(i,m)^getsg(n-i,m))]=1;
    }
    for(int i=2;m-i>=2;i++){
        visited[(getsg(n,i)^getsg(n,m-i))]=1;
    }
    for(int i=0;;i++){
        if(!visited[i]){
            return sg[n][m]=i;
        }
    }
}
int main(){
    int n,m;
    memset(sg,-1,sizeof(sg));
    for(int i=1;i<=200;i++){
        sg[1][i]=1;
        sg[i][1]=1;
    }
    while(scanf("%d %d",&n,&m)!=EOF){
        int key=getsg(n,m);
        if(key) printf("WIN\n");
        else printf("LOSE\n");
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值