绝对,非常考耐心,细心的一道题目,这道题目充分的说明我是考虑问题不全面的人

所以现在看来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 }