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 }