题目背景

高高的星空,簇簇闪耀的群星形态万千。一个星座(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

说明

在这种情况下,天体图是一个长23宽为15的二维矩阵。请注意这幅天体图是对应(corresponds to)下面这个矩阵的图像。

Starry-2.gif 图starry-2:天体图

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

数据范围

0 <= 星空的长和宽 <= 100

0 <= 星座个数 <= 500

0 <= 不相似的星座个数 <= 26

1 <= 每个星座中星星个数 <= 160

------------------------------------------------------------------------------------

今天A了一道提高加的题目,心里美啧啧!

好了,自恋完毕,发题解咯(对不起打pascal的人,本人打C++),这道题一看,纯暴力!于是,我拿起了拳套,对电脑一顿猛砸(我最不擅长搜索!)

注:这道题是很好的一道搜索题,题目地址,练一下

但是,以我死猪不怕开水烫的毅力,想出了正解,首先,是输入:

scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++)
{
scanf("%s",st+1);
for(int j=1;j<=m;j++)
{
a[i][j]/*1或0*/=st[j]-'0';
if(a[i][j]==0)h[i][j]=true;/*判断这个点可不可以被搜索*/
}
}

然后,到了找星座了,定义八个方向,然后bfs一遍,求出来了,(注:本人比较喜欢x为横坐标​)

当然,​有人会说,找完星座,是不是要排序一遍,保证字典序,其实,只要在循环上做文章就行啦!

    for(int  i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)/*一格一格判断,这样保证按字典序,不信大家试一下*/
{
if(h[i][j]==false && a[i][j]==1)/*必须为1的点且没有找过*/
{
bfs(i,j,++k/*申请一个新的编号并遍历*/);
b[k].fa=k;/*并查集,后面讲怎么利用*/
}
}
}

bfs来一发​:

void  bfs(int  qx,int  qy,int  uk)
{
b[uk].len=head=1;tail=2;
list[head].x=b[uk].a[1].x=b[uk].min.x=b[uk].max.x=qx;
list[head].y=b[uk].a[1].y=b[uk].min.y=b[uk].max.y=qy;
ll[qx][qy]=uk;/*判断这个点归属哪个编号的星座*/
h[qx][qy]=true;/*循环前的初始化,这部分要重视,很容易出细节错误*/
while(head!=tail)
{
int x=list[head].x,y=list[head].y;
for(int i=0;i<=7;i++)/*八个方向*/
{
int tx=x+dx[i],ty=y+dy[i];
if(tx>0 && ty>0 && tx<=n && ty<=m && h[tx][ty]==false && a[tx][ty]==1)/*判断搜过没有*/
{
h[tx][ty]=true;
list[tail].x=tx;list[tail++].y=ty;
b[uk].a[++b[uk].len].x=tx;
b[uk].a[b[uk].len].y=ty;/*记录点*/
b[uk].min.x/*接下来四个点记录的是四个极点的坐标(我把星座当成在一个长方形里的一个图案)*/=mymin(b[uk].min.x,tx);
b[uk].min.y=mymin(b[uk].min.y,ty);
b[uk].max.x=mymax(b[uk].max.x,tx);
b[uk].max.y=mymax(b[uk].max.y,ty);
ll[tx][ty]=uk;/*找到后的一系列骚操作*/
}
}
head++;
}
sort(b[uk].a+1,b[uk].a+b[uk].len+1,cmp);/*排序,排序按横坐标从小到大,相等列坐标从小到大*/
}

然后,到了找相同,顺时针旋转90度的公式:x1,y1(旋转前),x2,y2(旋转后)(x表横坐标,y表列坐标)

x2=y1,y2=max.x(最大的横坐标!最小的为1)-x1+1

node  right(node  x)
{
int tx=x.max.x;
for(int i=1;i<=x.len;i++)
{
int oox=x.a[i].x,ooy=x.a[i].y;
x.a[i].x=ooy;
x.a[i].y=tx-oox+1;/*公式*/
}
swap(x.max.x,x.max.y);/*行列交换*/
sort(x.a+1,x.a+x.len+1,cmp);/*排序*/
return x;
}

但是,我们要注意,判断是为了防止出错,我们要把图案所位于的最小长方形移动到左上角的位置(以1,1,为min.x,min.y)

具体如下:

node  right(node  x)
{
int tx=x.max.x;
for(int i=1;i<=x.len;i++)
{
int oox=x.a[i].x,ooy=x.a[i].y;
x.a[i].x=ooy;
x.a[i].y=tx-oox+1;/*公式*/
}
swap(x.max.x,x.max.y);/*行列交换*/
sort(x.a+1,x.a+x.len+1,cmp);/*排序*/
return x;
}

还有水平翻转操作:

inline  node  fanzhuan(node  x)
{
for(int i=1;i<=x.len;i++)x.a[i].y=x.max.y-x.a[i].y+1;
sort(x.a+1,x.a+x.len+1,cmp);
return x;
}

判断:

inline  bool  pd(node  x,node  y)
{
for(int i=1;i<=x.len;i++)
{
if(x.a[i].x!=y.a[i].x || x.a[i].y!=y.a[i].y)return false;
}
return true;
}

最后附上并查集!

int  findfa(int  x)
{
if(b[x].fa!=x)b[x].fa=findfa(b[x].fa);/*记录现在的父亲*/
return b[x].fa;
}

所有的函数讲完了,就到的主函数

for(int  i=1;i<k;i++)
{
for(int j=i+1;j<=k;j++)
{
if(b[i].len==b[j].len)/*星星数相同才可能相同*/
{
node st1=yuchu(b[i]);
node st2=yuchu(b[j]);/*预处理*/
if(pd(st1,st2)==true)
{
int tfa=findfa(j);
b[i].fa=b[j].fa;/*认祖先,由于循环,这个点肯定还没认祖先(不算认自己)*/
break;/*加了并查集的潇洒*/
}
node stl1=right(st1);//旋转
if(pd(stl1,st2)==true)
{
int tfa=findfa(j);
b[i].fa=b[j].fa;
break;
}
stl1=right(stl1);
if(pd(stl1,st2)==true)
{
int tfa=findfa(j);
b[i].fa=b[j].fa;
break;
}
stl1=right(stl1);
if(pd(stl1,st2)==true)
{
int tfa=findfa(j);
b[i].fa=b[j].fa;
break;
}
stl1=fanzhuan(st1);//翻转
if(pd(stl1,st2)==true)
{
int tfa=findfa(j);
b[i].fa=b[j].fa;
break;
}
stl1=right(stl1);
if(pd(stl1,st2)==true)
{
int tfa=findfa(j);
b[i].fa=b[j].fa;
break;
}
stl1=right(stl1);
if(pd(stl1,st2)==true)
{
int tfa=findfa(j);
b[i].fa=b[j].fa;
break;
}
stl1=right(stl1);
if(pd(stl1,st2)==true)
{
int tfa=findfa(j);
b[i].fa=b[j].fa;
break;
}
//到这代表他们两不适合
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]!=0)
{
int tx=findfa(ll[i][j]);
int ty=ll[i][j];
if(oo[tx]/*代表这个星座是否有字母*/==0)oo[tx]=oo[ty]=++bibi;/*给他们申请一个新的字母*/
else oo[ty]=oo[tx];
printf("%c",oo[ty]+'a'-1);
}
else printf("0");
}
printf("\n");
}

至此,这题就A了,哈哈哈哈哈,喜欢点个赞呗

注:上面的图片侵权抱歉!

[USACO5.1]夜空繁星Starry Night的更多相关文章

  1. 几个H5炫酷特效

    那H5里有哪些高级动效了?小编仔细体验了国内不少几个优秀H5页面作品,整理出下面几个H5页面特效.我们的H5作品如果能用上其中一两个,相信能增色不少! 1.粒子特效 —>>一键爆炸 模拟现 ...

  2. 立方体贴图(Cubemap)

    http://blog.csdn.net/asdjy123/article/details/51190643 点击打开链接 好东西保存方便查看 立方体贴图(Cubemap) 原文 Cubemaps 作 ...

  3. (转)OpenGL学习——立方体贴图

    转自:https://learnopengl-cn.readthedocs.io/zh/latest/04%20Advanced%20OpenGL/06%20Cubemaps/ 我们之前一直使用的是2 ...

  4. 2018.06.29 NOIP模拟 繁星(前缀和)

    繁星 [问题描述] 要过六一了,大川正在绞尽脑汁想送给小伙伴什么礼物呢.突然想起以前拍过一张夜空中的繁星的照片,这张照片已经被处理成黑白的,也就是说,每个像素只可能是两个颜色之一,白或黑.像素(x,y ...

  5. 伙伴们休息啦canvas绘图夜空小屋

    HTML5 canvas绘图夜空小屋 伙伴们园友们,夜深了,休息啦,好人好梦... 查看效果:http://hovertree.com/texiao/html5/28/ 效果图如下: 代码如下: &l ...

  6. Vijos1881闪烁的繁星 [线段树]

    P1881闪烁的繁星  背景 繁星闪烁着--深蓝的太空何曾听得见他们对语沉默中微光里他们深深的互相颂赞了 描述 繁星, 漫天的繁星.繁星排成一列, 我数一数呀, 一共有N只小星星呢. 星星们是听话的好 ...

  7. HTML5夜空烟花绽放动画效果

    模板描述:HTML5夜空烟花绽放动画效果基于HTML5 canvas制作,模拟夜空烟花绽放动画效果,烟花会在夜空打出贺词,有新年快乐.合家幸福.万事如意.心想事成.财源广进等,文字可以自定义,做成各种 ...

  8. 【COGS1049】天空中的繁星

    [题目背景] 第二届『Citric』杯NOIP提高组模拟赛 第二题 [题目描述] Lemon最近买了一台数码相机.某天Lemon很无聊,于是对着夜空拍了一张照片,然后把照片导入了电脑.Lemon想依靠 ...

  9. vijos国庆节模拟赛之繁星春水

    A.闪烁的繁星 题目:https://vijos.org/p/1881 题解:貌似做过小白逛公园或者序列操作都可以秒出吧,就是pushup函数比较麻烦,不过仔细想一想就知道了. 代码: #includ ...

随机推荐

  1. 学习路线 roadmap

    我的学习路线为HTML > CSS > Javsscript:Javascript是前端一切学习的基础.HTML和css一起学习. JavaScript基础: Js基础教程.js内置对象常 ...

  2. 一道Java集合框架题

    问题:某班30个学生的学号为20070301-20070330,全部选修了Java程序设计课程,给出所有同学的成绩(可用随机数产生,范围60-100),请编写程序将本班各位同学的成绩按照从低到高排序打 ...

  3. .NET 自动内存管理(垃圾收集GC)

    自动内存管理(垃圾收集GC) 在面向对象的环境里, 要使用资源,必须为响应 的类型分配一定 的内存空间.下面是访问一个资源所需要的几个步骤: 1. 调用中间语言(IL)的newobj 指令.当我们用N ...

  4. SQL查询某一字段重复的数据

    查询出重复记录 select * from 数据表 WHERE 重复记录字段 in ( select 重复记录字段 from  数据表 group by 重复记录字段 having count(重复记 ...

  5. JavaScript 如何编写计算器

    1.JavaScript制作计算器 <!DOCTYPE html> <html> <head> <meta charset="UTF-8" ...

  6. Linux ELF格式分析

    http://www.cnblogs.com/hzl6255/p/3312262.html ELF, Executable and Linking Format, 是一种用于可执行文件.目标文件.共享 ...

  7. 编译安装 mysql 5.5,运行 cmake报错Curses library not found

    是因为 curses库没有安装,执行下面的语句即可 yum -y install ncurses-devel 如果上述命令的结果是no package,则使用下面的命令安装 apt-get insta ...

  8. css3中的 @Keyframes

    一.介绍 keyframes被称为关键帧,其类似于Flash中的关键帧.在CSS3中其主要以“@keyframes”开头,后面跟着是动画名称加上一对花括号“{…}”,括号中是一些不同时间段样式规则. ...

  9. 剑指offer 和为s的两个数字的调试

    这是整个调试, for (int i:s) cout<<i<<endl;这句话是c++11特性下的一种遍历方式 在编译的时候需要加-std=c++11,即g++ 41.cpp ...

  10. IE 兼容模式 设置 Meta Compatible 和 Iframe 子页面的关系

    背景 因为历史原因,之前很多的系统都会是 顶级页面+Iframe来加载子级页面的这种模式构件系统,而且系统都只能运行在IE6或者IE 高版本兼容模式下(IE 7模式). 随着现在的审美原来越高,脚本能 ...