2D-Nim

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 4066   Accepted: 1851

Description

The 2D-Nim board game is played on a grid, with pieces on the grid points. On each move, a player may remove any positive number of contiguous pieces in any row or column. The player who removes the last piece wins. For example, consider the left grid in the following figure.

The player on move may remove (A), (B), (A, B), (A, B, C), or (B,F), etc., but may not remove (A, C), (D, E), (H, I) or (B, G).
For purposes of writing 2D-Nim-playing software, a certain programmer wants to be able to tell whether or not a certain position has ever been analyzed previously. Because of the rules of 2D-Nim, it should be clear that the two boards above are essentially equivalent. That is, if there is a winning strategy for the left board, the same one must apply to the right board. The fact that the contiguous groups of pieces appear in different places and orientations is clearly irrelevant. All that matters is that the same clusters of pieces (a cluster being a set of contiguous pieces that can be reached from each other by a sequence of one-square vertical or horizontal moves) appear in each. For example, the cluster of pieces (A, B, C, F, G) appears on both boards, but it has been reflected (swapping left and right), rotated, and moved. Your task is to determine whether two given board states are equivalent in this sense or not.

Input

The first line of the input file contains a single integer t (1 ≤ t ≤ 10), the number of test cases, followed by the input data for each test case. The first line of each test case consists of three integers W, H, and n (1 ≤ W, H ≤ 100). W is the width, and H is the height of the grid in terms of the number of grid points. n is the number of pieces on each board. The second line of each test case contains a sequence of n pairs of integers xi , yi, giving the coordinates of the pieces on the first board (0 ≤ xi < W and 0 ≤ yi < H). The third line of the test case describes the coordinates of the pieces on the second board in the same format.

Output

Your program should produce a single line for each test case containing a word YES or NO indicating whether the two boards are equivalent or not.

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

Source

Tehran 2002, First Iran Nationwide Internet Programming Contest
 
分析:
需要依据题目,提取图像特征,特征一致则为YES,特征不一致则为NO。
解题:
提取了2个特征:
1)每一个点的邻接关系:统计四个方向上邻接点数量分布,即有0、1、2、3、4个点相邻的数量。
2)点的连通量:在纵向和横向两个方向上,统计连线点的分布,即有1、2、...、99、100个点连成一线的数量。
 
PS:这两个条件为必要不充分条件。discus中有用例我没跑过,但是poj AC了,poj的数据弱了。至于充分条件,目前我还没想出如何证明。
 
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 typedef struct
  6 {
  7     int width;
  8     int height;
  9     int num;
 10     int map[2][100][100];
 11 }Picture;
 12 
 13 typedef struct
 14 {
 15     int x;
 16     int y;
 17     int factor;
 18 }Piont;
 19 
 20 Picture pic;
 21 Piont points[2][10000];
 22 int factorCnt[2][5];
 23 int connectCnt[2][101];
 24 int connectMax[2];
 25 
 26 void Input()
 27 {
 28     int i, j, x, y = 0;
 29     memset(&pic, 0, sizeof(pic));
 30     scanf("%d %d %d", &pic.width, &pic.height, &pic.num);
 31 
 32     for(j = 0; j < 2; j++)
 33     {
 34         for(i = 0; i < pic.num; i++)
 35         {
 36             scanf("%d %d", &x, &y);
 37             pic.map[j][y][x] = 1;
 38             points[j][i].x = x;
 39             points[j][i].y = y;
 40         }
 41     }
 42 /*
 43     for(j = 0; j < 2; j++)
 44     {
 45         for(y = pic.height-1; y >= 0; y--)
 46         {
 47             for(x = 0; x < pic.width; x++)
 48             {
 49                 printf("%d ", pic.map[j][y][x]);
 50             }
 51             printf("\n");
 52         }
 53         printf("------------------------\n");
 54     }
 55 */
 56 }
 57 
 58 void CalcFactor()
 59 {
 60     int i, j, x, y, factor;
 61     memset(factorCnt, 0, sizeof(factorCnt));
 62     for(j = 0; j < 2; j++)
 63     {
 64         for(i = 0; i < pic.num; i++)
 65         {
 66             x = points[j][i].x;
 67             y = points[j][i].y;
 68             factor = (x > 0) ? pic.map[j][y][x-1] : 0;
 69             factor += (x < pic.width-1) ? pic.map[j][y][x+1] : 0;
 70             factor += (y > 0) ? pic.map[j][y-1][x] : 0;
 71             factor += (y < pic.height-1) ? pic.map[j][y+1][x] : 0;
 72             points[j][i].factor = factor;
 73             factorCnt[j][factor]++;
 74         }
 75     }
 76 /*
 77     for(j = 0; j < 2; j++)
 78     {
 79         for(i = 0; i < pic.num; i++)
 80         {
 81             printf("%d   ", points[j][i].factor);
 82         }
 83         printf("\n");
 84     }
 85     printf("------------------------\n");
 86 */
 87 }
 88 
 89 void CheckResult()
 90 {
 91     int i, j = 0;
 92     for(i = 0; i < 5; i++)
 93     {
 94         if(factorCnt[0][i] != factorCnt[1][i]) break;
 95     }
 96 
 97     if(connectMax[0] != connectMax[1])
 98     {
 99         printf("NO\n");
100         return;
101     }
102 
103     for(j = 0; j < connectMax[0]; j++)
104     {
105         if(connectCnt[0][j] != connectCnt[1][j]) break;
106     }
107 
108     if(i != 5 || j != connectMax[0])
109     {
110         printf("NO\n");
111     }
112     else
113     {
114         printf("YES\n");
115     }
116 }
117 
118 void CalcConnect()
119 {
120     int j, x, y, connect;
121     memset(connectMax, 0, sizeof(connectMax));
122     memset(connectCnt, 0, sizeof(connectCnt));
123     for(j = 0; j < 2; j++)
124     {
125         for(y = 0; y < pic.height; y++)
126         {
127             for(x = 0; x < pic.width; x++)
128             {
129                 if(pic.map[j][y][x] != 1) continue;
130                 connect = 1;
131                 while(++x < pic.width && pic.map[j][y][x] == 1)
132                 {
133                     connect++;
134                 }
135                 connectCnt[j][connect]++;
136                 if(connect > connectMax[j]) connectMax[j] = connect;
137             }
138         }
139 
140         for(x = 0; x < pic.width; x++)
141         {
142             for(y = 0; y < pic.height; y++)
143             {
144                 if(pic.map[j][y][x] != 1) continue;
145                 connect = 1;
146                 while(++y < pic.height && pic.map[j][y][x] == 1)
147                 {
148                     connect++;
149                 }
150                 connectCnt[j][connect]++;
151                 if(connect > connectMax[j]) connectMax[j] = connect;
152             }
153         }
154     }
155 }
156 
157 void Proc()
158 {
159     CalcFactor();
160     CalcConnect();
161     CheckResult();
162 }
163 
164 int main()
165 {
166     int num = 0;
167     scanf("%d", &num);
168     while(num--)
169     {
170         Input();
171         Proc();
172     }
173     return 0;
174 }