1457: 棋盘游戏

1457: 棋盘游戏

Time Limit: 5 Sec   Memory Limit: 64 MB
Submit: 327   Solved: 185
[ Submit][ Status][ Discuss]

Description

有一个100 * 100的棋盘,其中左下角的编号为(0, 0), 右上角编号为(99, 99)。棋盘上有N个Queen,最开始第i个Queen的位置为(Xi, Yi)。现在有两个玩家依次来操作,每一次一个玩家可以选择其中一个Queen,将它跳到(Xi – k, Yi)或(Xi, Yi - k)或(Xi – k, Yi - k), 其中k > 0。注意在游戏的过程中,一个格子里面可能出现多个Queen。如果谁先将任意一个Queen移动到(0, 0), 谁就获胜。问先手必胜还是后手必胜?

Input

注意本题是多组数据。 第一行有一个数T, 表示数据组数。 接下来有T组数据,每组数据的第一行一个正整数N表示Queen的个数。接下来N行每行两个数表示第i个Queen的初始位置Xi, Yi(0 <= Xi <= 99, 0 <= Yi <= 99)。

Output

对于每一组数据,你需要输出是先手必胜还是后手必胜。 如果是先手必胜,输出“^o^“, 如果是后手必胜,输出”T_T”。

Sample Input

2
2
3 4
3 5
3
3 2
4 2
3 1

Sample Output

^o^
T_T
数据范围
T <= 10, N <= 1000

HINT

Source

[ Submit][ Status][ Discuss]

考虑到是任意一个皇后到达(0,0)时游戏宣告结束,就不能将(0,0)设定为游戏的终止状态。
对于主对角线和(0,k)(k,0)这三类点,双方肯定都是避免将棋子移到上面, 因为这个时候后手一步取胜
那么就将终止状态设为(1,2)和(2,1)两个点,因为这两个点先手无论怎么移动,都是后手必胜
剩下的就是暴力搜一搜,用sg定理判断答案了,注意转移过程不能触碰到上述三类点
注意特判初始状态有皇后在以上三类点的情况。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
 
const int N = 100;
 
int T,n,cnt,sg[N][N],bo[N*N];
bool vis[N][N];
 
void Dfs(int x,int y)
{
    if (vis[x][y]) return;
    stack <int> s; vis[x][y] = 1;
    for (int k = 1; k < x; k++)
        if (x - k != y) Dfs(x - k,y),s.push(sg[x - k][y]);
    for (int k = 1; k < y; k++)
        if (y - k != x) Dfs(x,y - k),s.push(sg[x][y - k]);
    for (int k = 1; k < min(x,y); k++)
        Dfs(x - k,y - k),s.push(sg[x - k][y - k]);
    ++cnt; while (!s.empty()) bo[s.top()] = cnt,s.pop();
    for (int i = 0; ; i++)
        if (bo[i] != cnt) {sg[x][y] = i; return;}
}
 
void Check()
{
    scanf("%d",&n);
    int sum; bool flag; sum = flag = 0;
    while (n--)
    {
        int x,y; scanf("%d%d",&x,&y);
        if (!x || !y || x == y) flag = 1; else sum ^= sg[x][y];
    }
    puts(flag || sum ? "^o^" : "T_T");
}
 
int main()
{
    #ifdef DMC
        freopen("DMC.txt","r",stdin);
    #endif
     
    vis[1][2] = vis[2][1] = 1;
    for (int i = 1; i <= 99; i++)
        for (int j = 1; j <= 99; j++)
            if (i != j) Dfs(i,j);
    cin >> T; while (T--) Check();
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值