1021 2D-Nim

题目:

2D-Nim棋盘游戏在网格上进行,网格点上有碎片。在每次移动中,玩家可以移除任何行或列中任何正数的连续片段。删除最后一块的玩家获胜。例如,请考虑下图中的左侧网格。
移动中的玩家可以移除(A),(B),(A,B),(A,B,C)或(B,F)等,但可以不移除(A,C),(D ,E),(H,I)或(B,G)。
为了编写2D-Nim播放软件,某个程序员希望能够判断某个位置是否曾经被分析过。由于2D-Nim的规则,应该清楚的是上面的两块板基本上是等价的。也就是说,如果左棋盘有获胜策略,那么同一棋盘必须适用于正确的棋盘。事实上,连续的片段出现在不同的地方和方向上显然是无关紧要的。重要的是,每个部分中出现相同的碎片簇(簇是一组连续的碎片,可以通过一个方形的垂直或水平移动的顺序彼此到达)。例如,片组(A,B,C,F,G)出现在两个板上,但它已被反射(左右交换),旋转和移动。您的任务是确定两个给定的电路板状态在这个意义上是否相同。
输入
输入文件的第一行包含一个整数t(1≤t≤10),测试用例的数量,后跟每个测试用例的输入数据。每个测试用例的第一行由三个整数W,H和n(1≤W,H≤100)组成。 W是宽度,H是网格点数的网格高度。 n是每块板上的件数。每个测试用例的第二行包含n对整数xi,yi的序列,给出第一块板上的块的坐标(0≤xi<W且0≤yi<H)。测试用例的第三行以相同的格式描述了第二块板上的块的坐标。
输出
您的程序应为每个测试用例生成一行,其中包含单词YES或NO,指示两个板是否相同。
样例输入
2
8 5 11
0 0 1 0 2 0 5 0 7 0 1 1 2 1 5 1 3 3 5 2 4 4
0 4 0 3 0 2 1 1 1 4 1 3 3 3 5 2 6 2 7 2 7 4
8 5 11
0 0 1 0 2 0 5 0 7 0 1 1 2 1 5 1 3 3 6 1 4 4
0 4 0 3 0 2 1 1 1 4 1 3 3 3 5 2 6 2 7 2 7 4
样例输出

没有
#include <iostream>

using namespace std;

bool map[101][101];
int W, H, n;

struct dot
{
    int x, y;
}dots[100010];

int dot1[10000], dot2[10000];

void quicksort(int left, int right, int *dotx)
{
    int i, j, temp;
    if (left < right)
    {
        i = left, j = right, temp = dotx[left];
        while (i < j)
        {
            while (i < j&&dotx[j] >= temp) j--;
            dotx[i] = dotx[j];
            while (i < j&&dotx[i] <= temp) i++;
            dotx[j] = dotx[i];
        }
        dotx[i] = temp;
        quicksort(left, j - 1, dotx);
        quicksort(j + 1, right, dotx);
    }
}

void Count(int *dot, int i)
{
    int x, y, sum;
    sum = 0;
    x = dots[i].x;
    y = dots[i].y;
    y--;
    while (map[x][y] && y >= 0)         //统计左边点的个数
    {
        sum++;
        y--;
    }
    y = dots[i].y;
    y++;
    while (map[x][y] && y < H)         //统计右边点的个数
    {
        sum++;
        y++;
    }
    y = dots[i].y;
    x--;
    while (map[x][y] && x >= 0)         //统计下面点的个数
    {
        sum++;
        x--;
    }
    x = dots[i].x;
    x++;
    while (map[x][y] && x < W)         //统计上面点的个数
    {
        sum++;
        x++;
    }
    dot[i] = sum;
}

int main()
{
    int t;
    cin >> t;
    int sum1, sum2;
    while (t--)
    {
        sum1 = sum2 = 0;
        memset(map, false, sizeof(map));
        cin >> W >> H >> n;
        for (int i = 1; i <= n; i++)          //输入第一组点
        {
            cin >> dots[i].x >> dots[i].y;
            map[dots[i].x][dots[i].y] = true;
        }
        for (int i = 1; i <= n; i++)
            Count(dot1, i), sum1 += dot1[i];                   //第一张图的连续点数
        memset(map, false, sizeof(map));
        for (int i = 1; i <= n; i++)          //输入第二组点
        {
            cin >> dots[i].x >> dots[i].y;
            map[dots[i].x][dots[i].y] = true;
        }
        for (int i = 1; i <= n; i++)
            Count(dot2, i), sum2 += dot2[i];                   //第二张图的连续点数
        if (sum1 != sum2) cout << "NO" << endl;
        else
        {
            quicksort(1, n, dot1);
            quicksort(1, n, dot2);
            int flag = 1;
            for (int i = 1; i <= n; i++)
            {
                if (dot1[i] != dot2[i])
                {
                                        //我之前在这里写了输出用来看数据的
                                        //我提交的时候忘记删了,结果还对了
                                        //不得不说这测试数据是真的水
                    flag = 0;
                    break;
                }
            }
            if (flag) cout << "YES" << endl;
            else cout << "NO" << endl;
        }
    }
}

来源:http://bk.bk3r.com/?f=s2gou&br3rd=1&wn=1&hid=99_16_16_0_&ty3=0&tryno=1509

posted on 2019-09-14 02:06  姜姜糖  阅读(181)  评论(0编辑  收藏  举报