HDU2873 Bomb Game(二维SG函数)

在BombGame中,两名玩家John和Jack在n*m的棋盘上进行游戏,棋盘上有初始放置的炸弹。游戏的目标是通过引爆炸弹来生成更多的炸弹,直到一方无法再引爆为止。本文介绍了一个解决方案,利用SG函数和NIM和的概念,通过预计算二维SG值表来判断最终胜利者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Bomb Game

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 806    Accepted Submission(s): 392


 

Problem Description

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.

 

 

Input

There are several test cases, each one begins with two integers n and m, 0<n, m<=50, represents the number of rows and columns. Following by an n*m grid, describing the initial situation, ‘#’ indicates bomb.
The input is terminated by n=m=0.

 

 

Output

For each test case, output one line, the name of the winner.

 

 

Sample Input

2 2 
.# 
.. 
2 2 
.# 
.# 
0 0

Sample Output

John 
Jack

题意:给定n*m的棋盘,棋盘中有炸弹,每进行一次操作炸弹炸一次,炸一次生成两个炸弹,分别位于左方和上方(左或上是边界则不生成),炸完之后原炸弹消失,两人轮流操作,最后不能引爆的输。

思路:

      一维的情况,等价于多堆取石子的游戏,sg值即石子数,本题中也就是到1,1的距离。

     二维时,引爆每个炸弹后会产生两个新的炸弹,而这个炸弹的sg即可看做新产生的两个炸弹的sg的异或(即"NIM和"),这样只要修改一下一维求sg的函数,变可以构造出二维的sg函数表,对应有炸弹的位置的sg值异或起来就可以判定胜负。

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int sg[55][55];
int get_sg(int x,int y)
{
    bool mex[1111];
    memset(mex,0,sizeof(mex));
    for(int i=0;i<x;i++)
        for(int j=0;j<y;j++)
            mex[sg[x][j]^sg[i][y]]=1;
    for(int i=0;;i++)
        if(!mex[i])
            return i;
}
void init()
{
    for(int i=0;i<55;i++)
        sg[i][0]=i,//i行上方石子总数
        sg[0][i]=i;//i列左边石子总数
    for(int i=1;i<55;i++)
        for(int j=1;j<55;j++)
            sg[i][j]=get_sg(i,j);
}
int main()
{
    init();//打表
    int x,y;
    while(~scanf("%d%d",&x,&y)&&x&&y)
    {
        int sum=0;
        char s[55][55];
        for(int i=0;i<x;i++)
        {
            scanf("%s",s[i]);
            for(int j=0;j<y;j++)
                if(s[i][j]=='#')
                    sum^=sg[i][j];
        }
        if(sum)
            printf("John\n");//先手赢
        else
            printf("Jack\n");//后手赢
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值