POJ - 1175 Starry Night

High up in the night sky, the shining stars appear in clusters of various shapes. A cluster is a non-empty group of neighbouring stars, adjacent in horizontal, vertical or diagonal direction. A cluster cannot be a part of a larger cluster. 

Clusters may be similar. Two clusters are similar if they have the same shape and number of stars, irrespective of their orientation. In general, the number of possible orientations for a cluster is eight, as Figure 1 exemplifies. 

POJ - 1175 Starry Night


The night sky is represented by a sky map, which is a two-dimensional matrix of 0's and 1's. A cell contains the digit 1 if it has a star, and the digit 0 otherwise. 

Given a sky map, mark all the clusters with lower case letters. Similar clusters must be marked with the same letter; non-similar clusters must be marked with different letters. You mark a cluster with a lower case letter by replacing every 1 in the cluster by that lower case letter. The order of allocation of letters depends on the first appearance of different clusters, from top to bottom and from left to right. 

Input

Your program is to read from standard input. The first two lines contain, respectively, the width W and the height H of a sky map. The sky map is given in the following H lines, of W characters each. 

0 <= W (width of the sky map) <= 100 
0 <= H (height of the sky map) <= 100 
0 <= Number of clusters <= 500 
0 <= Number of non-similar clusters <= 26 (a..z) 
1 <= Number of stars per cluster <= 160

Output

Your program is to write to standard output. The output contains the same map as the input, except that the clusters are marked as described above.

Sample Input

23
15
10001000000000010000000
01111100011111000101101
01000000010001000111111
00000000010101000101111
00000111010001000000000
00001001011111000000000
10000001000000000000000
00101000000111110010000
00001000000100010011111
00000001110101010100010
00000100110100010000000
00010001110111110000000
00100001110000000100000
00001000100001000100101
00000001110001000111000

Sample Output

a000a0000000000b0000000
0aaaaa000ccccc000d0dd0d
0a0000000c000c000dddddd
000000000c0b0c000d0dddd
00000eee0c000c000000000
0000e00e0ccccc000000000
b000000e000000000000000
00b0f000000ccccc00a0000
0000f000000c000c00aaaaa
0000000ddd0c0b0c0a000a0
00000b00dd0c000c0000000
000g000ddd0ccccc0000000
00g0000ddd0000000e00000
0000b000d0000f000e00e0b
0000000ddd000f000eee000

Hint

Just to make it clearer, notice that this sample input corresponds to the following picture of the sky. 

POJ - 1175 Starry Night


Notice that this sample output corresponds to the following picture. 

POJ - 1175 Starry Night

 

题目大意:1 代表星,0代表不是,八个方向的星星连在一起组成了星团。给星团起一个编号  a、b、c.......,实际就是把属于一个星团的星星换成a、b、等等。但是 要求 如果形状大小相同的星团、那么编号就用同一个。如果a星团已经有了,再次发现的星团跟a这个星团的形状大小一样,那么他也是编号为a。

难点:如何判断星团相同,(旋转后的图形也是相同)、看大佬博客:如果图形的 每个点 与其他所有点的距离之和相同的话,那么两个图形就是相同的。

具体看代码解释:
 

#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
struct node {
	int cnt;  //星团中星星的个数(1的个数) 
	int x[210],y[210]; //星团中每个星星的坐标 
	int belong;  // 这个星团属于哪个编号 
	double s;   // 计算星团点与点距离之和,判断星团是否与别的星团相同 
} star[520]; 
int n,m;
int map[150][150]; //存图 
int vis[150][150]; 
int	len,now; // len 代表星团的个数,也代表了星团的编号,now代表星团的编号 
int dir[8][2]= {0,1,0,-1,1,0,1,-1,-1,1,-1,-1,1,1,1,-1}; //8 个方向搜索 

int check(int lon) {  // 计算星团的点与点距离,并且判断是否已经出现过相同的星团 
	star[lon].s = 0;
	for(int i=1; i<=star[lon].cnt; i++) {
		for(int j=1; j<=star[lon].cnt; j++) {
			star[lon].s+= sqrt((star[lon].x[i]-star[lon].x[j])*(star[lon].x[i]-star[lon].x[j]) *1.0 + (star[lon].y[i]-star[lon].y[j])*(star[lon].y[i]-star[lon].y[j]));
		}
	}
//	printf("s: %.2lf\n",star[lon].s);
	for(int i=1; i<lon; i++) {
		if(fabs(star[i].s - star[lon].s)<=0.00000001) {
			return star[i].belong;  // 如果星团已经出现过,那么返回这个星团的编号,且本星团的编号与其相同 
		}
	}
	return -1;
}

void dfs(int x,int y) {  //dfs 搜索 
	int xx,yy;
	int t = ++star[len].cnt;  
	star[len].x[t]=x;     //将属于本星团的星星的坐标存入 
	star[len].y[t]=y;
	vis[x][y] = len;    
	for(int i = 0; i < 8; i ++) {
		xx = x+dir[i][0];
		yy = y+dir[i][1];
		if(xx>=1 && yy>=1 && xx<=m && yy<=n && vis[xx][yy]==0 && map[xx][yy]==1) {
			dfs(xx,yy);
		}
	}
}

int main() {
	char ch[150];
	len = 0;
	now = 0;
	int t;
	scanf("%d%d",&n,&m);
	for(int i=1; i<=m; i++) {
		for(int j=1; j<=n; j++) {
			scanf("%1d",&t);
			if(t==1) map[i][j]=true;
			else     map[i][j]=false;
		}
	}
	for(int i=1; i<=m; i++) {
		for(int j=1; j<=n; j++) {
			if(vis[i][j]==0 && map[i][j] == 1) { //出现没有被搜索的星星 
				++len; 
				dfs(i,j);
				int res = check(len);  //是否是已经出现过的星团 
				if(res == -1) {
					star[len].belong = ++now;
				} else {
					star[len].belong = res;
				}
			}
		}
	}
	for(int i=1; i<=m; i++) {
		for(int j=1; j<=n; j++) {
			if(map[i][j]==1) {
				printf("%c",star[vis[i][j]].belong-1+'a'); 
			} else
				printf("%d",map[i][j]);
		}
		printf("\n");
	}
	return 0;
}