• 洛谷 P2749 [USACO5.1]【夜空繁星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 }
  • 相关阅读:
    utils:一个通用枚举类
    代码片段(二):SQL片段
    Scala:(一) 特点及安装环境配置
    Scala:(二) 语言基础-数据结构、表达式(判断、循环、块表达式)
    11-docker搭建mysql一主一从
    10-docker搭建rabbitmq集群
    尚硅谷周阳面试第二季
    docker 修改mysql 表大小写铭感
    volatile的理解
    消息队列优缺点及其选型
  • 原文地址:https://www.cnblogs.com/hualian/p/11205538.html
Copyright © 2020-2023  润新知