【夜空繁星Starry Night】

题目背景

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

题目描述

夜空可以表示为一份天体图(sky map),它是一个由字符0和1组成的二维矩阵,字符1表示所在的位置有一颗星;字符0表示该位置上是空的.给定一份天体图,用同一个小写英文标识(mark)相似的所有星座。相似的星座必须用相同的字母标识,不同的星座表示为不同的字母。标识一个星座,就是将其中各星体对应的字符1替换为相应的小写字母.

输入输出格式

输入格式:

文件的前两行分别记录了天体图的宽度W、深度H。而天体图则是由接下来的H行表示,每行包括W个字符. ……

输出格式:

输出文件记录了天体图与文件STARRY.IN相似,不同之处在于,各个星座按照“任务”中的要求进行了标识(mark)。

对于同一个输入文件,可能会有很多不同的标识,此时,输出字典序最小的标识。

输入输出样例

输入样例#1: 

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

输出样例#1:

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

解题思路

  这道题就是标准的找联通块,但是它的星系可以旋转八个方向,这个判重就很麻烦,所以我们就用一个简单的数学道理来判重:两个图形,如果它们自身的任意两点的距离和相等,证明它们是同一图形。

题解

  1 #include<bits/stdc++.h>
  2 #define N 105
  3 using namespace std;
  4 int n,m,Star=0;//当前星系的种类 
  5 bool flag[N][N];//搜索时的标记 
  6 char mp[N][N];//存图 
  7 double star[N];//每个星系的距离之和 
  8 int dir[8][2]={0,1,0,-1,1,0,-1,0,1,1,1,-1,-1,1,-1,-1};//八个方向 
  9 struct node{//坐标 
 10     int x;
 11     int y;
 12 };
 13 node galaxy[N];//搜到的当前星系的每一个星星的坐标 
 14 void Galaxy(int x)//处理当前星系的字母 
 15 {
 16     double ans=0;//距离总和 
 17     int flag=0;
 18     for(int i=1;i<=x;i++)
 19     {
 20         for(int j=1;j<=x;j++)
 21         {
 22             ans+=sqrt((galaxy[i].x-galaxy[j].x)*(galaxy[i].x-galaxy[j].x)+(galaxy[i].y-galaxy[j].y)*(galaxy[i].y-galaxy[j].y));
 23         //平面内两点距离公式 
 24         }
 25     }
 26     for(int i=1;i<=Star;i++)
 27     {
 28         if(fabs(star[i]-ans)<=0.00001)//如果相差小于0.00001,我们判断为同一星系 
 29         {
 30             flag=i;//记录星系,方便存字母 
 31             break;
 32         }
 33     }
 34     if(!flag)//如果它是一个新的星系 
 35     {
 36         Star++;//星系种类增加 
 37         star[Star]=ans;
 38         for(int i=1;i<=x;i++)
 39         {
 40             mp[galaxy[i].x][galaxy[i].y]='a'+Star-1;//存储字母 
 41         }
 42         return;
 43     }
 44     for(int i=1;i<=x;i++)
 45     {
 46         mp[galaxy[i].x][galaxy[i].y]='a'+flag-1;//找相似星星的字母 
 47     }
 48 }
 49 void bfs(int x,int y)//找联通块 
 50 {
 51     int num=1;//开始就起点一颗星星 
 52     queue<node> q;
 53     q.push((node){x,y});
 54     flag[x][y]=true;///标记 
 55     galaxy[num]=(node){x,y};//记录坐标 
 56     while(!q.empty())
 57     {
 58         node head=q.front();
 59         q.pop();
 60         for(int i=0;i<8;i++)
 61         {
 62             int tx=head.x+dir[i][0];
 63             int ty=head.y+dir[i][1];
 64             if(tx>=1&&ty>=1&&tx<=n&&ty<=m&&!flag[tx][ty]&&mp[tx][ty]=='1')//越界与标记 
 65             {
 66                 flag[tx][ty]=true;
 67                 num++;//这个星系里的星星数量增加 
 68                 galaxy[num]=(node){tx,ty};//存储坐标 
 69                 q.push((node){tx,ty});
 70             }
 71         }
 72     }
 73     Galaxy(num);//开始判断这个星系 
 74 }
 75 int main()
 76 {
 77     cin>>m>>n;
 78     for(int i=1;i<=n;i++)
 79     {
 80         for(int j=1;j<=m;j++)
 81         {
 82             cin>>mp[i][j];//存图 
 83         }
 84     }
 85     for(int i=1;i<=n;i++)
 86     {
 87         for(int j=1;j<=m;j++)
 88         {
 89             if(!flag[i][j]&&mp[i][j]=='1')//没被搜过的星星开始找星系 
 90             {
 91                 bfs(i,j);
 92             }
 93         }
 94     }
 95     for(int i=1;i<=n;i++)
 96     {
 97         for(int j=1;j<=m;j++)
 98         {
 99             cout<<mp[i][j];//输出 
100         }
101         cout<<endl;
102     }
103 }

猜你喜欢

转载自www.cnblogs.com/hualian/p/11205538.html