北大poj-1021

2D-Nim

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

Descriptionapp

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.

Inputide

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.

Outputui

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 Inputthis

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 Outputspa

YES
NO

Sourcecode

Tehran 2002, First Iran Nationwide Internet Programming Contest
 
分析:
須要依據題目,提取圖像特徵,特徵一致則爲YES,特徵不一致則爲NO。
解題:
提取了2個特徵:
1)每個點的鄰接關係:統計四個方向上鄰接點數量分佈,即有0、一、二、三、4個點相鄰的數量。
2)點的連通量:在縱向和橫向兩個方向上,統計連線點的分佈,即有一、二、...、9九、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 }
相關文章
相關標籤/搜索