John and Jack, two mathematicians, created a game called “Bomb Game” at spared time. This game is played on an n*m chessboard. A pair of integers (p, q) represents the grid at row p, column q. Some bombs were placed on the chessboard at the beginning. Every round, a player can choose to explode a bomb located at (p, q), and the exploded bomb will disappear. Furthermore:
1.If p>1 and q>1, the bomb will split up into two bombs located at (u, q) and (p, v), u<p, v<q, u and v are chosen by the player.
2.If p=1 and q>1, one new bomb will be produced, located at (p, v), v<q, v can be chosen freely by the player.
3.If q=1 and p>1, one new bomb will be produced, located at (u, q), u<p, u can be chosen freely by the player.
If two bombs located at the same position or a bomb located at (1, 1), they will be exploded automatically without producing new bombs.
Two players play in turn, until one player cannot explode the bombs and loses the game.
John always plays first.
Now, we’ll give you an initial situation, and you should tell us who will win at last. Assume John and Jack are smart enough, and they always do the best choice.
1.If p>1 and q>1, the bomb will split up into two bombs located at (u, q) and (p, v), u<p, v<q, u and v are chosen by the player.
2.If p=1 and q>1, one new bomb will be produced, located at (p, v), v<q, v can be chosen freely by the player.
3.If q=1 and p>1, one new bomb will be produced, located at (u, q), u<p, u can be chosen freely by the player.
If two bombs located at the same position or a bomb located at (1, 1), they will be exploded automatically without producing new bombs.
Two players play in turn, until one player cannot explode the bombs and loses the game.
John always plays first.
Now, we’ll give you an initial situation, and you should tell us who will win at last. Assume John and Jack are smart enough, and they always do the best choice.
The input is terminated by n=m=0.
2 2 .# .. 2 2 .# .# 0 0
John Jack
题意:
给个棋盘,'#'是炸弹,'.'是空位,john和jack每回合引爆一个炸弹,但是会在原炸弹的上方和左方任意处产生新的炸弹(新炸弹不能超出棋盘的边界),如果有两个炸弹在同一个位置或者炸弹在左上角,炸弹会自动爆炸,谁不能引爆炸弹谁就输,john先手,输出胜利者的名字。
思路:
可以知道:
1.sg[0][0]=0; 左上角的炸弹sg值为0
2.sg[i][0]=sg[0][i]=i; 在棋盘边界的炸弹的sg值为行或列的值
3.如果两个炸弹在同一个格子里,爆不爆炸都对结果无影响,爆炸sg为0,不爆炸两个炸弹的sg值相同,异或之后也是0
因为坐标不断地向左上角靠近,所以可以看成nim博弈的问题,只需要遍历分裂的炸弹即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <stack>
#define INF 0x3f3f3f3f
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int maxn=55;
int sg[maxn][maxn];
int n, m;
char pl[maxn][maxn];
int get_sg(int x, int y)
{
if(sg[x][y]!=-1)
return sg[x][y];
bool vis[maxn*maxn]={false};
for(int i=0; i<x; i++)
for(int j=0; j<y; j++)
vis[get_sg(i, y)^get_sg(x, j)]=true; //标记子状态
for(int i=0; ; i++)
if(!vis[i])
return i;
}
void init()
{
for(int i=0; i<maxn; i++)
sg[i][0]=sg[0][i]=i;
for(int i=0; i<maxn; i++)
for(int j=0; j<maxn ;j++)
sg[i][j]=get_sg(i, j);
}
int main()
{
memset(sg, -1, sizeof(sg));
init();
while(~scanf("%d%d", &n, &m))
{
getchar();
if((n+m)==0)
break;
int ans=0;
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
scanf("%c", &pl[i][j]);
if(pl[i][j]=='#')
ans^=sg[i][j];
}
getchar();
}
if(ans)
printf("John\n");
else
printf("Jack\n");
}
return 0;
}