[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
说明
在这种情况下,天体图是一个长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的更多相关文章
- 几个H5炫酷特效
那H5里有哪些高级动效了?小编仔细体验了国内不少几个优秀H5页面作品,整理出下面几个H5页面特效.我们的H5作品如果能用上其中一两个,相信能增色不少! 1.粒子特效 —>>一键爆炸 模拟现 ...
- 立方体贴图(Cubemap)
http://blog.csdn.net/asdjy123/article/details/51190643 点击打开链接 好东西保存方便查看 立方体贴图(Cubemap) 原文 Cubemaps 作 ...
- (转)OpenGL学习——立方体贴图
转自:https://learnopengl-cn.readthedocs.io/zh/latest/04%20Advanced%20OpenGL/06%20Cubemaps/ 我们之前一直使用的是2 ...
- 2018.06.29 NOIP模拟 繁星(前缀和)
繁星 [问题描述] 要过六一了,大川正在绞尽脑汁想送给小伙伴什么礼物呢.突然想起以前拍过一张夜空中的繁星的照片,这张照片已经被处理成黑白的,也就是说,每个像素只可能是两个颜色之一,白或黑.像素(x,y ...
- 伙伴们休息啦canvas绘图夜空小屋
HTML5 canvas绘图夜空小屋 伙伴们园友们,夜深了,休息啦,好人好梦... 查看效果:http://hovertree.com/texiao/html5/28/ 效果图如下: 代码如下: &l ...
- Vijos1881闪烁的繁星 [线段树]
P1881闪烁的繁星 背景 繁星闪烁着--深蓝的太空何曾听得见他们对语沉默中微光里他们深深的互相颂赞了 描述 繁星, 漫天的繁星.繁星排成一列, 我数一数呀, 一共有N只小星星呢. 星星们是听话的好 ...
- HTML5夜空烟花绽放动画效果
模板描述:HTML5夜空烟花绽放动画效果基于HTML5 canvas制作,模拟夜空烟花绽放动画效果,烟花会在夜空打出贺词,有新年快乐.合家幸福.万事如意.心想事成.财源广进等,文字可以自定义,做成各种 ...
- 【COGS1049】天空中的繁星
[题目背景] 第二届『Citric』杯NOIP提高组模拟赛 第二题 [题目描述] Lemon最近买了一台数码相机.某天Lemon很无聊,于是对着夜空拍了一张照片,然后把照片导入了电脑.Lemon想依靠 ...
- vijos国庆节模拟赛之繁星春水
A.闪烁的繁星 题目:https://vijos.org/p/1881 题解:貌似做过小白逛公园或者序列操作都可以秒出吧,就是pushup函数比较麻烦,不过仔细想一想就知道了. 代码: #includ ...
随机推荐
- BZOJ3329: Xorequ(二进制数位dp 矩阵快速幂)
题意 题目链接 Sol 挺套路的一道题 首先把式子移一下项 \(x \oplus 2x = 3x\) 有一件显然的事情:\(a \oplus b \leqslant c\) 又因为\(a \oplus ...
- SourceTree 跳过登陆
当前只有Win的版本,Mac自行百度(笑) 很多人用git命令行不熟练,那么可以尝试使用sourcetree进行操作. 然鹅~~sourcetree又一个比较严肃的问题就是,很多人不会跳过注册或者操作 ...
- iOS开发之Objective-c的AES256加密和解密算法的实现
原文:http://www.lidaren.com/archives/1470 高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法. 以下实现 ...
- CAD鼠标移动到对象时显示对象内容
//定义事件 Editor ed = doc.Editor; ed.PointMonitor += new PointMonitorEventHandler(ed_Po ...
- Android GreenDAO 3.0 不修改版本号的情况下增加、删除表、添加字段
最近项目中使用了GreenDAO的3.0以上的版本,出现需要增加删除表的需求,刚开始用,发现官方对增加和删除的方法是每次去修改数据库版本号,版本一旦升级,那么原来数据库中的表会全部删除再重建.太麻烦, ...
- scss的使用方式(环境搭建)
我用的是Koala. IDE是intellij_idea(其他IDE也可) 下载Koala:http://koala-app.com/ 2.安装(选好位置,下一步即可) 3.打开Koala,创建项目 ...
- 如何找到Android app启动activity和页面元素信息
在实施app自动化的时候,我们需要知道app 的启动activity和页面元素信息,以此启动app和定位页面元素,那么如何在没有源码的情况下找打他们呢?当然是有好的工具啦,有Android sdk自带 ...
- jstl Maven 依赖导致的 Jar 包冲突
概述 Jar 包冲突是日常开发过程中,时常会遇到的问题.本文介绍由 jstl 的 Maven 依赖导致的 Jar 包冲突问题,以及对应的解决方法. jstl 的 Maven 依赖配置 <depe ...
- http缓存基本介绍
https://www.helloweba.com/view-blog-414.html
- HDU(1698),线段树区间更新
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 区间更新重点在于懒惰标记. 当你更新的区间就是整个区间的时候,直接sum[rt] = c*(r- ...