题目背景

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

    1001 #include <bits/stdc++.h> using namespace std; vector<long long> v; long long pow2(l ...

  2. (生产)js-base64 - 转码

    参考:https://github.com/dankogai/js-base64 安装 $ npm install --save js-base64 使用 var Base64 = require(' ...

  3. 夜色的 cocos2d-x 开发笔记 00

    第一次写博客,本人还是大二学生,纯新手,无论是文章的技术性,还是参考性,都不高,但却是根据我的经历,开发过的真实过程,对自己记载一些备忘的笔记,更希望也能帮到一些人. 本人用的win7 + vs201 ...

  4. Azure进阶攻略 | 应用流畅运行杜绝超载,自有一套好方法

    世界上很多东西,无论交通工具.房屋建筑,甚至计算机程序,在容量方面都存在设计上的理论最大值. 比如火车,正常情况下是这样的.舒适地坐着,安静地读一本书,时不时抬头若有所思地远眺车窗外风景,满满的文艺范 ...

  5. Spring Boot项目Circular view path问题解决

    使用Spring Boot创建Spring MVC项目,访问url请求出现问题:Circular view path 1.问题描述 控制台打印: javax.servlet.ServletExcept ...

  6. C#或Net连接Oracle操作提示 Oracle 客户端 version 8.1.7 或更高版本报错

    异常问题 远程连接ORCALE 服务器,而本地未安装任何ORCALE 相关客户端及ODAC .using System.Data.OracleClient;当我们用程序操作Oracle库的时候,OPE ...

  7. php网站修改默认访问文件的nginx配置

    搭建好lnmp后,有时候并不需要直接访问index.php,配置其他的默认访问文件比如index.html这时候需要配置一下nginx才能访问到你想要设置的文件 直接上代码,如下是我的配置的一份简单的 ...

  8. 在ABAP里取得一个数据库表记录数的两种方法

    方法1:使用函数EM_GET_NUMBER_OF_ENTRIES 这个函数使用起来很简单,只需要将想查询的数据库表名称维护进输入参数IT_TABLES: 上图说明这个函数支持批量操作,我查询的两张表名 ...

  9. 【BZOJ3506】[CQOI2014] 排序机械臂(Splay)

    点此看题面 大致题意: 给你\(n\)个数.第一次找到最小值所在位置\(P_1\),翻转\([1,P_1]\),第二次找到剩余数中最小值所在位置\(P_2\),翻转\([2,P_2]\),以此类推.求 ...

  10. 【[TJOI2018]异或】

    写板子了,可持久化\(Trie\)的板子了 其实和主席树写法类似,还是存好左右儿子之后存好权值 之后差分去查询就好了 这道题第一问我们直接\(dfs\)序转化成区间 第二问搞成\(x,y,lca(x, ...