POJ1021 2D-Nim

题目来源:http://poj.org/problem?id=1021

题目大意:

  有一种在棋盘上玩的游戏,每一步,一个玩家可以从棋盘上拿走连续行或列的棋子。谁拿到最后一颗棋子就胜利。如下图所示的棋盘,玩家可以拿走 (A), (B), (A, B), (A, B, C), 或 (B,F),等,但不能拿走(A, C), (D, E), (H, I) 或(B, G)。

  仔细看上面两个棋盘,会发现其实他们是等价的。左边棋盘的取胜策略也可以用到右边的棋盘上。两盘棋子的连续块的形状是等价的,可以通过旋转、镜像和平移进行映射。程序的任务是判断两个棋盘是否等价。

输入:第一行为测试用例数。每个测试用例的第一行有三个整数W,H和n(1,<=W,H<=100).W和H为棋盘宽和高,n是棋盘上棋子个数。第二行有n对整数。xi,yi表示第一个棋盘棋子的坐标。(0<=xi<=W,0<=yi<=H).第三行为第二个棋盘的棋子分布。

输出:若两棋盘等价输出YES,否则输出NO。


Sample Input

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

Sample Output

YES
NO

牛人给出的方法:求出两个棋盘中每个有点的位置的度数(该点向4个方向可以走的步数之和),分别对两个棋盘棋子按度数排序,若两个序列相等输入YES,否则NO。(图形变换后,每个点的度数不变)

  1 //////////////////////////////////////////////////////////////////////////
  2 //        POJ1021 2D-Nim
  3 //        Memory: 428K        Time: 16MS
  4 //        Language: C++        Result: Accepted
  5 //////////////////////////////////////////////////////////////////////////
  6 
  7 #include <iostream> 
  8 using namespace std;
  9 class Point {
 10 public:
 11     bool t;
 12     int degree;
 13 };
 14 
 15 int compare(const void * a, const void * b) {
 16     return (*(Point *)a).degree - (*(Point *)b).degree;
 17 }
 18 
 19 int main() {
 20     int ncase;
 21     cin >> ncase;
 22     for (int caseNo = 1; caseNo <= ncase; ++caseNo) {
 23         int H, W, n;
 24         Point points1[100 * 100];
 25         Point points2[100 * 100];
 26 
 27         cin >> W >> H >> n;
 28         for (int w = 0; w < W; ++w) {
 29             for (int h = 0; h < H; ++h) {
 30                 points1[h * W + w].t = false;
 31                 points1[h * W + w].degree = 0;
 32                 points2[h * W + w].t = false;
 33                 points2[h * W + w].degree = 0;
 34 
 35             }
 36         }
 37         for (int i = 0; i < n; ++i) {
 38             int w, h;
 39             cin >> w >> h;
 40             points1[h * W + w].t = true;
 41         }
 42         for (int i = 0; i < n; ++i) {
 43             int w, h;
 44             cin >> w >> h;
 45             points2[h * W + w].t = true;
 46         }
 47         for (int w = 0; w < W; ++w) {
 48             for (int h = 0; h < H; ++h) {
 49                 if (points1[h * W + w].t == true) {
 50                     int i = 1;
 51                     while (h + i < H) {
 52                         if (points1[(h + i) * W + w].t == true) {
 53                             ++points1[h * W + w].degree;
 54                             ++i;
 55                         } else {
 56                             break;
 57                         }
 58                     }
 59                     i = 1;
 60                     while (h - i >= 0) {
 61                         if (points1[(h - i) * W + w].t == true) {
 62                             ++points1[h * W + w].degree;
 63                             ++i;
 64                         } else {
 65                             break;
 66                         }
 67                     }
 68                     i = 1;
 69                     while (w + i < W) {
 70                         if (points1[h * W + w + i].t == true) {
 71                             ++points1[h * W + w].degree;
 72                             ++i;
 73                         } else {
 74                             break;
 75                         }
 76                     }
 77                     i = 1;
 78                     while (w - i >= 0) {
 79                         if (points1[h * W + w - i].t == true) {
 80                             ++points1[h * W + w].degree;
 81                             ++i;
 82                         } else {
 83                             break;
 84                         }
 85                     }
 86                 }
 87                 if (points2[h * W + w].t == true) {
 88                     int i = 1;
 89                     while (h + i < H) {
 90                         if (points2[(h + i) * W + w].t == true) {
 91                             ++points2[h * W + w].degree;
 92                             ++i;
 93                         } else {
 94                             break;
 95                         }
 96                     }
 97                     i = 1;
 98                     while (h - i >= 0) {
 99                         if (points2[(h - i) * W + w].t == true) {
100                             ++points2[h * W + w].degree;
101                             ++i;
102                         } else {
103                             break;
104                         }
105                     }
106                     i = 1;
107                     while (w + i < W) {
108                         if (points2[h * W + w + i].t == true) {
109                             ++points2[h * W + w].degree;
110                             ++i;
111                         } else {
112                             break;
113                         }
114                     }
115                     i = 1;
116                     while (w - i >= 0) {
117                         if (points2[h * W + w - i].t == true) {
118                             ++points2[h * W + w].degree;
119                             ++i;
120                         } else {
121                             break;
122                         }
123                     }
124                 }
125             }
126         }
127         qsort(points1, H * W, sizeof(Point), compare);
128         qsort(points2, H * W, sizeof(Point), compare);
129         bool ok = true;
130         for (int i = 0; i < H * W; ++i) {
131             if (points1[i].degree != points2[i].degree) {
132                 ok = false;
133                 break;
134             }
135         }
136         if (ok) {
137             cout << "YES" << endl;
138         } else {
139             cout << "NO" << endl;
140         }
141     }
142     system("pause");
143     return 0;
144 }
View Code
posted @ 2013-07-31 17:07  小菜刷题史  阅读(817)  评论(0编辑  收藏  举报