Starry Night

题意:转载NOCOW翻译(http://www.nocow.cn/index.php/Translate:USACO/starry

描述

高高的星空,簇簇闪耀的群星形态万千。一个星座(cluster)是一群连通的星组成的非空集合,所谓连通是指水平,垂直或者对角相邻。一个星座不能是另一个更大星座的一部分, 星座可以相似(similar)。如果两个星座有相同的形状,而且包括相同数目的星体,那么不管其方向性如何,就算相似。一般而言,星座可能的方向有八个,如图1所示。


Starry-1.gif

图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

Starry-2.gif

[编辑]SAMPLE OUTPUT (file starry.out)

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

这是上述输入实例的一个可能的结果。请注意,该输出文件对应于下面的天空景象。

Starry-3.gif

[编辑]Constraints

0 <= W (天体图的宽度) <= 100

0 <= H (天体图的深度) <= 100

0 <= 星座的数目 <= 500

0 <= 不相似的星座数目 <= 26 (a..z)

1 <= 各星座包含的星体数目 <= 160


解题思路:

  1. 从上到下,从左到右,DFS分组。
  2. 在分组过程中判重
  3. 判重方法:判定两个点集是否重复,先将点集中的点按照“先上后下,先左后右”排序,如果两个点集中相对应的点的坐标差固定,则点集重复。分别用旋转和轴对称来处理其中一个点集中的点,来列举“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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值