绝对,非常考耐心,细心的一道题目,这道题目充分的说明我是考虑问题不全面的人
所以现在看来TopCoder的测试数据还都算是比较弱的,真的没有极其变态的,而且TopCoder的题目其实没有超级复杂的,或许是因为我从来没做过第三题吧。
回正题。
这道题目其实一看就知道怎么做,但是就一个字烦
首先你要用FloodFill把所有的Cluster标注出来,这个不难,而且速度很快,时间差不多也就线性的。因为你只需要遍历一遍就可以了。
问题就出在判别一个Cluster的图案以前是否出现过。
首先一个Pattern可以有8种不同的样子,这里我们就不考虑对称的那些特殊情况了,就按一般情况考虑,默认这8种都不相同。
然后你需要把除了已知的一种的剩下七种全部弄出来,其实也不需要全部,不过最差情况你肯定要全弄出来,这种情况发生在出现新的图案的时候。
然后呢,你就跟这些图案去比较,看看是不是相同,这又是一个问题,关键问题,怎么判断是不是一样!
我刚开始的做法就是,记录一个图案的左上角和右下角,也就是minx,miny,maxy,maxy
当我用FloodFill找到了一个新的Cluster的时候,我会在搜索的过程中记录当前这个图案的左上角和右下角
然后就是和已知的每个图案去比较
比较的时候,我把当前的Cluster通过变换生产不同的变种,然后去跟已知的每个图案比较。
我的问题就出在这里了,因为我是用四个角标记一个图案的,那么,很有可能,这个矩形的范围内包括不属于这个图案的点。
例如
0010
1010
0111
1111
很明显,大的那个图案的矩形框左上角是(0,0),右下角是(3,3)
这就把那个不属于他的1包含进去了。
于是,在将两个矩形进行比较的时候,必须要处理这种“噪声”元素。
按照我的这种图案记录方式,我无论怎么判断,似乎都是不行的
于是我只能改策略了,用一个Shape类来记录每一个一致的图案,注意,是精确的记录,不包含那些杂点。
而且只记录第一次出现的,因为在后面陆陆续续出现的图案中,有可能两个一样的图案的矩形框有重叠。
例如
000100000
000100000
000100000
111111100
000101000
000101000
000001000
001111111
000001000
000001000
我们可以看到,这两个“十字架”的矩形框是有重叠的。
我只是精确的记录第一次出现的图案
然后,每次用两个“纯净”的图去比较,也就是说
一是我刚刚FloodFill出来的Cluster,我会用‘2’去标记,注意是字符2
另外一个就是我一致的Shape
这样我就只需要比较他们两个图有标注的地方,如果这些地方有不一致,那么显然不是same的
其实就这么简单的事情,如果写成为代码,我估计5行都用不了。
但是我却写了200多行。
为了能节省时间,旋转90,180,270我是分别写的
所以现在看来TopCoder的测试数据还都算是比较弱的,真的没有极其变态的,而且TopCoder的题目其实没有超级复杂的,或许是因为我从来没做过第三题吧。
回正题。
这道题目其实一看就知道怎么做,但是就一个字烦
首先你要用FloodFill把所有的Cluster标注出来,这个不难,而且速度很快,时间差不多也就线性的。因为你只需要遍历一遍就可以了。
问题就出在判别一个Cluster的图案以前是否出现过。
首先一个Pattern可以有8种不同的样子,这里我们就不考虑对称的那些特殊情况了,就按一般情况考虑,默认这8种都不相同。
然后你需要把除了已知的一种的剩下七种全部弄出来,其实也不需要全部,不过最差情况你肯定要全弄出来,这种情况发生在出现新的图案的时候。
然后呢,你就跟这些图案去比较,看看是不是相同,这又是一个问题,关键问题,怎么判断是不是一样!
我刚开始的做法就是,记录一个图案的左上角和右下角,也就是minx,miny,maxy,maxy
当我用FloodFill找到了一个新的Cluster的时候,我会在搜索的过程中记录当前这个图案的左上角和右下角
然后就是和已知的每个图案去比较
比较的时候,我把当前的Cluster通过变换生产不同的变种,然后去跟已知的每个图案比较。
我的问题就出在这里了,因为我是用四个角标记一个图案的,那么,很有可能,这个矩形的范围内包括不属于这个图案的点。
例如
0010
1010
0111
1111
很明显,大的那个图案的矩形框左上角是(0,0),右下角是(3,3)
这就把那个不属于他的1包含进去了。
于是,在将两个矩形进行比较的时候,必须要处理这种“噪声”元素。
按照我的这种图案记录方式,我无论怎么判断,似乎都是不行的
于是我只能改策略了,用一个Shape类来记录每一个一致的图案,注意,是精确的记录,不包含那些杂点。
而且只记录第一次出现的,因为在后面陆陆续续出现的图案中,有可能两个一样的图案的矩形框有重叠。
例如
000100000
000100000
000100000
111111100
000101000
000101000
000001000
001111111
000001000
000001000
我们可以看到,这两个“十字架”的矩形框是有重叠的。
我只是精确的记录第一次出现的图案
然后,每次用两个“纯净”的图去比较,也就是说
一是我刚刚FloodFill出来的Cluster,我会用‘2’去标记,注意是字符2
另外一个就是我一致的Shape
这样我就只需要比较他们两个图有标注的地方,如果这些地方有不一致,那么显然不是same的
其实就这么简单的事情,如果写成为代码,我估计5行都用不了。
但是我却写了200多行。
为了能节省时间,旋转90,180,270我是分别写的
1
import
java.io.
*
;
2 /*
3 ID: yanglei4
4 LANG: JAVA
5 TASK:starry
6 */
7 public class starry{
8 public class shape {
9 public int minx,miny,maxx,maxy;
10 public int [][] pattern;
11 shape( int a, int b, int c, int d) {
12 minx = a;
13 miny = b;
14 maxx = c;
15 maxy = d;
16 pattern = new int [maxx - minx + 1 ][maxy - miny + 1 ];
17 }
18
19 public int getHeight() {
20 return maxx - minx + 1 ;
21 }
22
23 public int getWidth() {
24 return maxy - miny + 1 ;
25 }
26 }
27 shape[] shapes = new shape[ 126 ];
28
29 boolean [][] visited;
30 int [][] sky;
31 int H,W;
32 char assignedChar = ' a ' ;
33 int minx,miny,maxx,maxy;
34
35 int count = 0 ;
36 PrintWriter out;
37 public void floodFill( int x, int y) {
38 visited[x][y] = true ;
39 sky[x][y] = ' 2 ' ;
40 if (x - 1 >= 0 ) {
41 if (visited[x - 1 ][y] == false && sky[x - 1 ][y] == 1 ) {
42 if (x - 1 < minx)
43 minx = x - 1 ;
44 floodFill(x - 1 , y);
45 }
46 if (y - 1 >= 0 )
47 if (visited[x - 1 ][y - 1 ] == false && sky[x - 1 ][y - 1 ] == 1 ) {
48 if (x - 1 < minx)
49 minx = x - 1 ;
50 if (y - 1 < miny)
51 miny = y - 1 ;
52 floodFill(x - 1 , y - 1 );
53 }
54 if (y + 1 < W)
55 if (visited[x - 1 ][y + 1 ] == false && sky[x - 1 ][y + 1 ] == 1 ) {
56 if (x - 1 < minx)
57 minx = x - 1 ;
58 if (y + 1 > maxy)
59 maxy = y + 1 ;
60 floodFill(x - 1 , y + 1 );
61 }
62 }
63 if (y - 1 >= 0 )
64 if (visited[x][y - 1 ] == false && sky[x][y - 1 ] == 1 ) {
65 if (y - 1 < miny)
66 miny = y - 1 ;
67 floodFill(x, y - 1 );
68 }
69 if (y + 1 < W)
70 if (visited[x][y + 1 ] == false && sky[x][y + 1 ] == 1 ) {
71 if (y + 1 > maxy)
72 maxy = y + 1 ;
73 floodFill(x, y + 1 );
74 }
75
76 if (x + 1 < H) {
77 if (visited[x + 1 ][y] == false && sky[x + 1 ][y] == 1 ) {
78 if (x + 1 > maxx)
79 maxx = x + 1 ;
80 floodFill(x + 1 , y);
81 }
82 if (y - 1 >= 0 )
83 if (visited[x + 1 ][y - 1 ] == false && sky[x + 1 ][y - 1 ] == 1 ) {
84 if (x + 1 > maxx)
85 maxx = x + 1 ;
86 if (y - 1 < miny)
87 miny = y - 1 ;
88 floodFill(x + 1 , y - 1 );
89 }
90 if (y + 1 < W)
91 if (visited[x + 1 ][y + 1 ] == false && sky[x + 1 ][y + 1 ] == 1 ) {
92 if (x + 1 > maxx)
93 maxx = x + 1 ;
94 if (y + 1 > maxy)
95 maxy = y + 1 ;
96 floodFill(x + 1 , y + 1 );
97 }
98 }
99 }
100
101 public int [][] R90( int [][] source, int height, int width) {
102 int [][] result = new int [width][height];
103
104 for ( int i = 0 ; i < height; i ++ )
105 for ( int j = 0 ; j < width; j ++ )
106 result[j][height - i - 1 ] = source[i][j];
107
108 return result;
109 }
110
111 public int [][] R180( int [][] source, int height, int width) {
112 int [][] result = new int [height][width];
113
114 for ( int i = 0 ; i < height; i ++ )
115 for ( int j = 0 ; j < width; j ++ )
116 result[height - i - 1 ][width - j - 1 ] = source[i][j];
117
118 return result;
119 }
120
121 public int [][] L90( int [][] source, int height, int width) {
122 int [][] result = new int [width][height];
123
124 for ( int i = 0 ; i < height; i ++ )
125 for ( int j = 0 ; j < width; j ++ )
126 result[width - j - 1 ][i] = source[i][j];
127
128 return result;
129 }
130
131 public int [][] Flip( int [][] source, int height, int width) {
132 int [][] result = new int [height][width];
133
134 for ( int i = 0 ; i < height; i ++ )
135 for ( int j = 0 ; j < width; j ++ )
136 result[i][j] = source[i][width - j - 1 ];
137 return result;
138 }
139
140 public boolean isSame( int [][] source, int [][] dest, int height, int width, int pattern) {
141 for ( int i = 0 ; i < height; i ++ )
142 for ( int j = 0 ; j < width; j ++ ) {
143 if ((dest[i][j] == pattern + 1 && source[i][j] != ' 2 ' ) || (dest[i][j] != pattern + 1 && source[i][j] == ' 2 ' )) return false ;
144 }
145 return true ;
146 }
147
148 public int checkSame() {
149
150 int height = maxx - minx + 1 ;
151 int width = maxy - miny + 1 ;
152
153 int [][] dest = new int [height][width];
154
155 for ( int i = minx; i <= maxx; i ++ )
156 for ( int j = miny; j <= maxy; j ++ )
157 if (sky[i][j] == ' 2 ' )
158 dest[i - minx][j - miny] = sky[i][j];
159
160
161 boolean same = false ;
162 int i = 0 ;
163 for (i = 0 ; i < count; i ++ ) {
164 // copy the shape
165 int [][] source = new int [shapes[i].getHeight()][shapes[i].getWidth()];
166 for ( int a = 0 ; a < shapes[i].getHeight(); a ++ )
167 for ( int b = 0 ; b < shapes[i].getWidth(); b ++ )
168 source[a][b] = shapes[i].pattern[a][b];
169
170 if (shapes[i].getHeight() == height && shapes[i].getWidth() == width) {
171 if (isSame(dest,source,height,width,i) == true ||
172 isSame(Flip(dest, height, width),source,height,width,i) == true ||
173 isSame(R180(dest,height,width),source, height,width,i) == true ||
174 isSame( Flip(R180(dest,height,width), height, width),source, height,width,i) == true ) {
175 same = true ;
176 break ;
177 }
178
179 }
180 if (shapes[i].getWidth() == height && shapes[i].getHeight() == width) {
181 if (isSame(R90(dest,height,width), source, width, height,i) == true ||
182 isSame(L90(dest,height,width), source, width, height,i) == true ||
183 isSame(Flip(R90(dest,height,width), width, height), source, width,height,i) == true ||
184 isSame(Flip(L90(dest,height,width), width, height), source, width,height,i) == true ) {
185 same = true ;
186 break ;
187 }
188 }
189 }
190
191 if ( ! same)
192 {
193 shapes[count] = new shape(minx,miny,maxx,maxy);
194 for ( int a = 0 ; a < height; a ++ )
195 for ( int b = 0 ; b < width; b ++ )
196 if (dest[a][b] == ' 2 ' )
197 shapes[i].pattern[a][b] = count + 1 ;
198 count ++ ;
199 return 0 ;
200 }
201 else
202 return i + 1 ;
203 }
204 public void done() throws IOException {
205 BufferedReader f = new BufferedReader( new FileReader( " starry.in " ));
206 out = new PrintWriter( new BufferedWriter( new FileWriter( " starry.out " )));
207 W = Integer.parseInt(f.readLine());
208 H = Integer.parseInt(f.readLine());
209
210 sky = new int [H][W];
211 visited = new boolean [H][W];
212
213 for ( int i = 0 ; i < H; i ++ ) {
214 String temp = f.readLine();
215 int len = temp.length();
216 for ( int j = 0 ; j < len; j ++ )
217 sky[i][j] = temp.charAt(j) - ' 0 ' ;
218 }
219 for ( int i = 0 ; i < H; i ++ )
220 for ( int j = 0 ; j < W; j ++ )
221 if (visited[i][j] == false && sky[i][j] == 1 ) {
222 minx = maxx = i;
223 miny = maxy = j;
224 floodFill(i,j);
225 // System.out.println("[" + minx + "," + miny + "][" + maxx + "," + maxy + "]");
226 int temp = checkSame();
227 if (temp == 0 )
228 temp = count;
229 for ( int a = minx; a <= maxx; a ++ )
230 for ( int b = miny; b <= maxy; b ++ )
231 if (sky[a][b] == ' 2 ' ) sky[a][b] = temp;
232 }
233 print();
234 out.close();
235 }
236
237 public void print() {
238 for ( int i = 0 ; i < H; i ++ ) {
239 for ( int j = 0 ; j < W; j ++ )
240 if (sky[i][j] != 0 )
241 out.print(( char )(sky[i][j] + ' a ' - 1 ));
242 else
243 out.print( " 0 " );
244 out.println();
245 }
246 }
247 public static void main(String[] args) throws IOException {
248 starry t = new starry();
249 t.done();
250 System.exit( 0 );
251 }
252 }
2 /*
3 ID: yanglei4
4 LANG: JAVA
5 TASK:starry
6 */
7 public class starry{
8 public class shape {
9 public int minx,miny,maxx,maxy;
10 public int [][] pattern;
11 shape( int a, int b, int c, int d) {
12 minx = a;
13 miny = b;
14 maxx = c;
15 maxy = d;
16 pattern = new int [maxx - minx + 1 ][maxy - miny + 1 ];
17 }
18
19 public int getHeight() {
20 return maxx - minx + 1 ;
21 }
22
23 public int getWidth() {
24 return maxy - miny + 1 ;
25 }
26 }
27 shape[] shapes = new shape[ 126 ];
28
29 boolean [][] visited;
30 int [][] sky;
31 int H,W;
32 char assignedChar = ' a ' ;
33 int minx,miny,maxx,maxy;
34
35 int count = 0 ;
36 PrintWriter out;
37 public void floodFill( int x, int y) {
38 visited[x][y] = true ;
39 sky[x][y] = ' 2 ' ;
40 if (x - 1 >= 0 ) {
41 if (visited[x - 1 ][y] == false && sky[x - 1 ][y] == 1 ) {
42 if (x - 1 < minx)
43 minx = x - 1 ;
44 floodFill(x - 1 , y);
45 }
46 if (y - 1 >= 0 )
47 if (visited[x - 1 ][y - 1 ] == false && sky[x - 1 ][y - 1 ] == 1 ) {
48 if (x - 1 < minx)
49 minx = x - 1 ;
50 if (y - 1 < miny)
51 miny = y - 1 ;
52 floodFill(x - 1 , y - 1 );
53 }
54 if (y + 1 < W)
55 if (visited[x - 1 ][y + 1 ] == false && sky[x - 1 ][y + 1 ] == 1 ) {
56 if (x - 1 < minx)
57 minx = x - 1 ;
58 if (y + 1 > maxy)
59 maxy = y + 1 ;
60 floodFill(x - 1 , y + 1 );
61 }
62 }
63 if (y - 1 >= 0 )
64 if (visited[x][y - 1 ] == false && sky[x][y - 1 ] == 1 ) {
65 if (y - 1 < miny)
66 miny = y - 1 ;
67 floodFill(x, y - 1 );
68 }
69 if (y + 1 < W)
70 if (visited[x][y + 1 ] == false && sky[x][y + 1 ] == 1 ) {
71 if (y + 1 > maxy)
72 maxy = y + 1 ;
73 floodFill(x, y + 1 );
74 }
75
76 if (x + 1 < H) {
77 if (visited[x + 1 ][y] == false && sky[x + 1 ][y] == 1 ) {
78 if (x + 1 > maxx)
79 maxx = x + 1 ;
80 floodFill(x + 1 , y);
81 }
82 if (y - 1 >= 0 )
83 if (visited[x + 1 ][y - 1 ] == false && sky[x + 1 ][y - 1 ] == 1 ) {
84 if (x + 1 > maxx)
85 maxx = x + 1 ;
86 if (y - 1 < miny)
87 miny = y - 1 ;
88 floodFill(x + 1 , y - 1 );
89 }
90 if (y + 1 < W)
91 if (visited[x + 1 ][y + 1 ] == false && sky[x + 1 ][y + 1 ] == 1 ) {
92 if (x + 1 > maxx)
93 maxx = x + 1 ;
94 if (y + 1 > maxy)
95 maxy = y + 1 ;
96 floodFill(x + 1 , y + 1 );
97 }
98 }
99 }
100
101 public int [][] R90( int [][] source, int height, int width) {
102 int [][] result = new int [width][height];
103
104 for ( int i = 0 ; i < height; i ++ )
105 for ( int j = 0 ; j < width; j ++ )
106 result[j][height - i - 1 ] = source[i][j];
107
108 return result;
109 }
110
111 public int [][] R180( int [][] source, int height, int width) {
112 int [][] result = new int [height][width];
113
114 for ( int i = 0 ; i < height; i ++ )
115 for ( int j = 0 ; j < width; j ++ )
116 result[height - i - 1 ][width - j - 1 ] = source[i][j];
117
118 return result;
119 }
120
121 public int [][] L90( int [][] source, int height, int width) {
122 int [][] result = new int [width][height];
123
124 for ( int i = 0 ; i < height; i ++ )
125 for ( int j = 0 ; j < width; j ++ )
126 result[width - j - 1 ][i] = source[i][j];
127
128 return result;
129 }
130
131 public int [][] Flip( int [][] source, int height, int width) {
132 int [][] result = new int [height][width];
133
134 for ( int i = 0 ; i < height; i ++ )
135 for ( int j = 0 ; j < width; j ++ )
136 result[i][j] = source[i][width - j - 1 ];
137 return result;
138 }
139
140 public boolean isSame( int [][] source, int [][] dest, int height, int width, int pattern) {
141 for ( int i = 0 ; i < height; i ++ )
142 for ( int j = 0 ; j < width; j ++ ) {
143 if ((dest[i][j] == pattern + 1 && source[i][j] != ' 2 ' ) || (dest[i][j] != pattern + 1 && source[i][j] == ' 2 ' )) return false ;
144 }
145 return true ;
146 }
147
148 public int checkSame() {
149
150 int height = maxx - minx + 1 ;
151 int width = maxy - miny + 1 ;
152
153 int [][] dest = new int [height][width];
154
155 for ( int i = minx; i <= maxx; i ++ )
156 for ( int j = miny; j <= maxy; j ++ )
157 if (sky[i][j] == ' 2 ' )
158 dest[i - minx][j - miny] = sky[i][j];
159
160
161 boolean same = false ;
162 int i = 0 ;
163 for (i = 0 ; i < count; i ++ ) {
164 // copy the shape
165 int [][] source = new int [shapes[i].getHeight()][shapes[i].getWidth()];
166 for ( int a = 0 ; a < shapes[i].getHeight(); a ++ )
167 for ( int b = 0 ; b < shapes[i].getWidth(); b ++ )
168 source[a][b] = shapes[i].pattern[a][b];
169
170 if (shapes[i].getHeight() == height && shapes[i].getWidth() == width) {
171 if (isSame(dest,source,height,width,i) == true ||
172 isSame(Flip(dest, height, width),source,height,width,i) == true ||
173 isSame(R180(dest,height,width),source, height,width,i) == true ||
174 isSame( Flip(R180(dest,height,width), height, width),source, height,width,i) == true ) {
175 same = true ;
176 break ;
177 }
178
179 }
180 if (shapes[i].getWidth() == height && shapes[i].getHeight() == width) {
181 if (isSame(R90(dest,height,width), source, width, height,i) == true ||
182 isSame(L90(dest,height,width), source, width, height,i) == true ||
183 isSame(Flip(R90(dest,height,width), width, height), source, width,height,i) == true ||
184 isSame(Flip(L90(dest,height,width), width, height), source, width,height,i) == true ) {
185 same = true ;
186 break ;
187 }
188 }
189 }
190
191 if ( ! same)
192 {
193 shapes[count] = new shape(minx,miny,maxx,maxy);
194 for ( int a = 0 ; a < height; a ++ )
195 for ( int b = 0 ; b < width; b ++ )
196 if (dest[a][b] == ' 2 ' )
197 shapes[i].pattern[a][b] = count + 1 ;
198 count ++ ;
199 return 0 ;
200 }
201 else
202 return i + 1 ;
203 }
204 public void done() throws IOException {
205 BufferedReader f = new BufferedReader( new FileReader( " starry.in " ));
206 out = new PrintWriter( new BufferedWriter( new FileWriter( " starry.out " )));
207 W = Integer.parseInt(f.readLine());
208 H = Integer.parseInt(f.readLine());
209
210 sky = new int [H][W];
211 visited = new boolean [H][W];
212
213 for ( int i = 0 ; i < H; i ++ ) {
214 String temp = f.readLine();
215 int len = temp.length();
216 for ( int j = 0 ; j < len; j ++ )
217 sky[i][j] = temp.charAt(j) - ' 0 ' ;
218 }
219 for ( int i = 0 ; i < H; i ++ )
220 for ( int j = 0 ; j < W; j ++ )
221 if (visited[i][j] == false && sky[i][j] == 1 ) {
222 minx = maxx = i;
223 miny = maxy = j;
224 floodFill(i,j);
225 // System.out.println("[" + minx + "," + miny + "][" + maxx + "," + maxy + "]");
226 int temp = checkSame();
227 if (temp == 0 )
228 temp = count;
229 for ( int a = minx; a <= maxx; a ++ )
230 for ( int b = miny; b <= maxy; b ++ )
231 if (sky[a][b] == ' 2 ' ) sky[a][b] = temp;
232 }
233 print();
234 out.close();
235 }
236
237 public void print() {
238 for ( int i = 0 ; i < H; i ++ ) {
239 for ( int j = 0 ; j < W; j ++ )
240 if (sky[i][j] != 0 )
241 out.print(( char )(sky[i][j] + ' a ' - 1 ));
242 else
243 out.print( " 0 " );
244 out.println();
245 }
246 }
247 public static void main(String[] args) throws IOException {
248 starry t = new starry();
249 t.done();
250 System.exit( 0 );
251 }
252 }