题目背景

高高的星空,簇簇闪耀的群星形态万千。一个星座(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. Spring课程 Spring入门篇 1-3Spring框架

    课程链接: 1 框架与类库的区别: 框架封装了逻辑,高内聚,类库是松散的工具组合 框架专注于某一个领域,类库通用性较强 2 为什么使用框架: a 业务系统日趋复杂 b 重用度高,开发效率和质量提高 c ...

  2. C#开发短信的方法和简介(转)

    http://ce.sysu.edu.cn/hope2008/Education/ShowArticle.asp?ArticleID=6337(来自) 自己收藏哈子

  3. 错误Cannot find module 'stylus'

    vue项目中使用stylus预处理器写css语法,老是出现 Cannot find module ‘stylus’ 的错误,鼓捣了很久,包括webstorm中配置stylus的支持,安装依赖. 终于找 ...

  4. android 扇形菜单

    引言: android中的菜单与windows的菜单没有什么区别,基本就是一个矩形框,如下: 这个菜单有多么能经得住历史的考验我就不多说了!我们再来看看最新有关手机可操作区域的调查 有此可以看出屏幕越 ...

  5. Java—继承

    继承 继承是类与类的一种关系,是一种“is a”的关系.注意:java中的继承是单继承,一个类只有一个父类. 继承的好处:子类拥有父类的所有属性和方法(private修饰的无效),实现代码的复用 语法 ...

  6. Excel操作之VLOOKUP函数

    1.作用 VLOOKUP函数是Excel中的一个纵向查找函数,它与LOOKUP函数和HLOOKUP函数属于一类函数,在工作中都有广泛应用,例如可以用来核对数据,多个表格之间快速导入数据等函数功能.功能 ...

  7. vue - 绑定css、style

    1.绑定html css1.1对象语法: 传给 v-bind:class 一个对象,以动态地切换 class <div v-bind:class="{ active: isActive ...

  8. 20145238-荆玉茗《Java程序设计》课程总结

    每周读书笔记链接汇总 第一周读书笔记: 第二周读书笔记: 第三周读书笔记: 第四周读书笔记: 第五周读书笔记: 第六周读书笔记: 第七周读书笔记: 第八周读书笔记: 第九周读书笔记: 实验报告链接汇总 ...

  9. ioc 的好文章 转自 GavinJun

    https://www.cnblogs.com/fuchongjundream/p/3873073.html

  10. 第16章 STM32中断应用概览—零死角玩转STM32-F429系列

    第16章     STM32中断应用概览 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fi ...