题意:转载NOCOW翻译(http://www.nocow.cn/index.php/Translate:USACO/starry)
描述
高高的星空,簇簇闪耀的群星形态万千。一个星座(cluster)是一群连通的星组成的非空集合,所谓连通是指水平,垂直或者对角相邻。一个星座不能是另一个更大星座的一部分, 星座可以相似(similar)。如果两个星座有相同的形状,而且包括相同数目的星体,那么不管其方向性如何,就算相似。一般而言,星座可能的方向有八个,如图1所示。
图1 相似的八个星座
夜空可以表示为一份天体图(sky map),它是一个由字符0和1组成的二维矩阵,字符1表示所在的位置有一颗星;字符0表示该位置上没有星.给定一份天体图,用同一个小写英文标识(mark)相似的所有星座。相似的星座必须用相同的字母标识,不同的星座表示为不同的字母。标识一个星座,就是将其中各星体对应的字符1替换为相应的小写字母.
[编辑]INPUT FORMAT
文件的前两行分别记录了天体图的宽度W、深度H。而天体图则是由接下来的H行表示,每行包括W个字符.
[编辑]OUTPUT FORMAT
输出文件记录了天体图与文件STARRY.IN相似,不同之处在于,各个星座按照“任务”中的要求进行了标识(mark)。 对于同一个输入文件,可能会有很多不同的标识,此时,输出字典序最小的标识。
[编辑]SAMPLE INPUT (file starry.in)
23 15 10001000000000010000000 01111100011111000101101 01000000010001000111111 00000000010101000101111 00000111010001000000000 00001001011111000000000 10000001000000000000000 00101000000111110010000 00001000000100010011111 00000001110101010100010 00000100110100010000000 00010001110111110000000 00100001110000000100000 00001000100001000100101 00000001110001000111000
[编辑]SAMPLE OUTPUT (file starry.out)
a000a0000000000b0000000 0aaaaa000ccccc000d0dd0d 0a0000000c000c000dddddd 000000000c0b0c000d0dddd 00000eee0c000c000000000 0000e00e0ccccc000000000 b000000e000000000000000 00b0f000000ccccc00a0000 0000f000000c000c00aaaaa 0000000ddd0c0b0c0a000a0 00000b00dd0c000c0000000 000g000ddd0ccccc0000000 00g0000ddd0000000e00000 0000b000d0000f000e00e0b 0000000ddd000f000eee000
这是上述输入实例的一个可能的结果。请注意,该输出文件对应于下面的天空景象。
[编辑]Constraints
0 <= W (天体图的宽度) <= 100
0 <= H (天体图的深度) <= 100
0 <= 星座的数目 <= 500
0 <= 不相似的星座数目 <= 26 (a..z)
1 <= 各星座包含的星体数目 <= 160
解题思路:
- 从上到下,从左到右,DFS分组。
- 在分组过程中判重
- 判重方法:判定两个点集是否重复,先将点集中的点按照“先上后下,先左后右”排序,如果两个点集中相对应的点的坐标差固定,则点集重复。分别用旋转和轴对称来处理其中一个点集中的点,来列举“8个状态”,处理后排序继续与另外一个点集比较。若有一次是重复的则判重,否则将不重复的点集排序后存储下来。
代码:
/*
ID: zc.rene1
LANG: C
PROG: starry
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_W 100
#define MAX_H 100
#define MAX_CLUSTERS 500
#define MAX_NON_SIMILAR 26
#define MAX_STARS 160
int W, H;
int sky[MAX_H + 2][MAX_W + 2];
char sky_result[MAX_H + 2][MAX_W + 2];
int visited[MAX_H + 2][MAX_W + 2];
int cluster_list[MAX_NON_SIMILAR][MAX_STARS][2];
int star_num[MAX_NON_SIMILAR];
int cluster_num;
int stack[MAX_STARS][2];
int store[MAX_STARS][2];
int store_cp[MAX_STARS][2];
int store_num;
void GetInput(FILE *fin)
{
int i, j;
char c;
memset(sky, 0, (MAX_H + 2) * (MAX_W + 2) * sizeof(int));
memset(sky_result, 0, (MAX_H + 2) * (MAX_W + 2) * sizeof(char));
fscanf(fin, "%d\n%d\n", &W, &H);
for (i=1; i<=H; i++)
{
for (j=1; j<=W; j++)
{
fscanf(fin, "%c", &c);
sky[i][j] = c - '0';
sky_result[i][j] = '0';
}
fscanf(fin, "%c", &c);
}
}
void SortStore()
{
int i, j;
int temp[2];
for (j=store_num-1; j>0; j--)
{
for (i=0; i<j; i++)
{
if (store[i][0] > store[i+1][0] || (store[i][0] == store[i+1][0] && store[i][1] > store[i+1][1]))
{
memcpy(temp, store[i], 2 * sizeof(int));
memcpy(store[i], store[i+1], 2 * sizeof(int));
memcpy(store[i+1], temp, 2 * sizeof(int));
}
}
}
}
void RotateStore(void)
{
int i, temp;
for (i=0; i<store_num; i++)
{
temp = store[i][1];
store[i][1] = store[i][0];
store[i][0] = (-temp);
}
}
int Equal(int index)
{
int detx, dety;
int tempx, tempy;
int i;
detx = cluster_list[index][0][0] - store[0][0];
dety = cluster_list[index][0][1] - store[0][1];
for (i=1; i<store_num; i++)
{
tempx = cluster_list[index][i][0] - store[i][0];
tempy = cluster_list[index][i][1] - store[i][1];
if (tempx != detx || tempy != dety)
{
return 0;
}
}
return 1;
}
void MirrorStore(void)
{
int i;
for (i=0; i<store_num; i++)
{
store[i][0] -= 2 * store[i][0];
}
}
int IsSimilar(int index)
{
int i;
if (store_num == 1)
{
return 1;
}
for (i=0; i<4; i++)
{
RotateStore();
SortStore();
if (Equal(index))
{
return 1;
}
}
MirrorStore();
for (i=0; i<4; i++)
{
RotateStore();
SortStore();
if (Equal(index))
{
return 1;
}
}
return 0;
}
int GetSimilarIndex(void)
{
int i;
for (i=0; i<cluster_num; i++)
{
if (star_num[i] == store_num)
{
if (IsSimilar(i))
{
return i;
}
}
}
return -1;
}
void SetSky(int index)
{
int i;
for (i=0; i<store_num; i++)
{
sky_result[store[i][0]][store[i][1]] = 'a' + index;
}
}
void DFS(int index_i, int index_j)
{
int bottom = -1, top = 0;
int m, n, i, j;
stack[top][0] = index_i;
stack[top][1] = index_j;
visited[index_i][index_j] = 1;
store_num = 0;
while (bottom < top)
{
m = stack[top][0];
n = stack[top][1];
top--;
store[store_num][0] = m;
store[store_num][1] = n;
store_num++;
for (i=-1; i<=1; i++)
{
for (j=-1; j<=1; j++)
{
if (visited[m + i][n + j] == 0 && sky[m + i][n + j] == 1)
{
top++;
stack[top][0] = m + i;
stack[top][1] = n + j;
visited[m + i][n + j] = 1;
}
}
}
}
memcpy(store_cp, store, MAX_STARS * 2 * sizeof(int));
i = GetSimilarIndex();
if (i == -1)
{
memcpy(store, store_cp, MAX_STARS * 2 * sizeof(int));
SortStore();
star_num[cluster_num] = store_num;
memcpy(cluster_list[cluster_num], store, MAX_STARS * 2 * sizeof(int));
cluster_num++;
SetSky(cluster_num - 1);
}
else
{
memcpy(store, store_cp, MAX_STARS * 2 * sizeof(int));
SetSky(i);
}
}
void ScanSky(void)
{
int i, j;
cluster_num = 0;
memset(cluster_list, 0, MAX_NON_SIMILAR * MAX_STARS * 2 * sizeof(int));
memset(star_num, 0, MAX_NON_SIMILAR * sizeof(int));
memset(visited, 0, (MAX_H + 2) * (MAX_W + 2) * sizeof(int));
for (i=1; i<=H; i++)
{
for (j=1; j<=W; j++)
{
if (visited[i][j] == 0 && sky[i][j] == 1)
{
DFS(i, j);
}
}
}
}
void PrintSky(FILE *fout)
{
int i, j;
for (i=1; i<=H; i++)
{
for (j=1; j<=W; j++)
{
fprintf(fout, "%c", sky_result[i][j]);
}
fprintf(fout, "\n");
}
}
int main(void)
{
FILE *fin, *fout;
fin = fopen("starry.in", "r");
fout = fopen("starry.out", "w");
GetInput(fin);
ScanSky();
PrintSky(fout);
return 0;
}