题目背景

高高的星空,簇簇闪耀的群星形态万千。一个星座(cluster)是一群连通的星组成的非空连通星系,这里的连通是指水平,垂直或者对角相邻的两个星星。一个星座不能是另一个更大星座的一部分, 星座可以相似(similar)。如果两个星座有相同的形状,而且包括相同数目的星体,那么不管其方向性如何,就算相似。一般而言,星座可能的方向有八个,如图1所示。

题目描述

夜空可以表示为一份天体图(sky map),它是一个由字符0和1组成的二维矩阵,字符1表示所在的位置有一颗星;字符0表示该位置上是空的.给定一份天体图,用同一个小写英文标识(mark)相似的所有星座。相似的星座必须用相同的字母标识,不同的星座表示为不同的字母。标识一个星座,就是将其中各星体对应的字符1替换为相应的小写字母.

输入输出格式

输入格式:

文件的前两行分别记录了天体图的宽度W、深度H。而天体图则是由接下来的H行表示,每行包括W个字符. ……

输出格式:

输出文件记录了天体图与文件STARRY.IN相似,不同之处在于,各个星座按照“任务”中的要求进行了标识(mark)。

对于同一个输入文件,可能会有很多不同的标识,此时,输出字典序最小的标识。

输入输出样例

输入样例#1: 复制

  1. 23
    15
    10001000000000010000000
    01111100011111000101101
    01000000010001000111111
    00000000010101000101111
    00000111010001000000000
    00001001011111000000000
    10000001000000000000000
    00101000000111110010000
    00001000000100010011111
    00000001110101010100010
    00000100110100010000000
    00010001110111110000000
    00100001110000000100000
    00001000100001000100101
    00000001110001000111000

输出样例#1: 复制

  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++),这道题一看,纯暴力!于是,我拿起了拳套,对电脑一顿猛砸(我最不擅长搜索!)

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

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

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

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

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

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

bfs来一发​:

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

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

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

  1. node right(node x)
  2. {
  3. int tx=x.max.x;
  4. for(int i=1;i<=x.len;i++)
  5. {
  6. int oox=x.a[i].x,ooy=x.a[i].y;
  7. x.a[i].x=ooy;
  8. x.a[i].y=tx-oox+1;/*公式*/
  9. }
  10. swap(x.max.x,x.max.y);/*行列交换*/
  11. sort(x.a+1,x.a+x.len+1,cmp);/*排序*/
  12. return x;
  13. }

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

具体如下:

  1. node right(node x)
  2. {
  3. int tx=x.max.x;
  4. for(int i=1;i<=x.len;i++)
  5. {
  6. int oox=x.a[i].x,ooy=x.a[i].y;
  7. x.a[i].x=ooy;
  8. x.a[i].y=tx-oox+1;/*公式*/
  9. }
  10. swap(x.max.x,x.max.y);/*行列交换*/
  11. sort(x.a+1,x.a+x.len+1,cmp);/*排序*/
  12. return x;
  13. }

还有水平翻转操作:

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

判断:

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

最后附上并查集!

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

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

  1. for(int i=1;i<k;i++)
  2. {
  3. for(int j=i+1;j<=k;j++)
  4. {
  5. if(b[i].len==b[j].len)/*星星数相同才可能相同*/
  6. {
  7. node st1=yuchu(b[i]);
  8. node st2=yuchu(b[j]);/*预处理*/
  9. if(pd(st1,st2)==true)
  10. {
  11. int tfa=findfa(j);
  12. b[i].fa=b[j].fa;/*认祖先,由于循环,这个点肯定还没认祖先(不算认自己)*/
  13. break;/*加了并查集的潇洒*/
  14. }
  15. node stl1=right(st1);//旋转
  16. if(pd(stl1,st2)==true)
  17. {
  18. int tfa=findfa(j);
  19. b[i].fa=b[j].fa;
  20. break;
  21. }
  22. stl1=right(stl1);
  23. if(pd(stl1,st2)==true)
  24. {
  25. int tfa=findfa(j);
  26. b[i].fa=b[j].fa;
  27. break;
  28. }
  29. stl1=right(stl1);
  30. if(pd(stl1,st2)==true)
  31. {
  32. int tfa=findfa(j);
  33. b[i].fa=b[j].fa;
  34. break;
  35. }
  36. stl1=fanzhuan(st1);//翻转
  37. if(pd(stl1,st2)==true)
  38. {
  39. int tfa=findfa(j);
  40. b[i].fa=b[j].fa;
  41. break;
  42. }
  43. stl1=right(stl1);
  44. if(pd(stl1,st2)==true)
  45. {
  46. int tfa=findfa(j);
  47. b[i].fa=b[j].fa;
  48. break;
  49. }
  50. stl1=right(stl1);
  51. if(pd(stl1,st2)==true)
  52. {
  53. int tfa=findfa(j);
  54. b[i].fa=b[j].fa;
  55. break;
  56. }
  57. stl1=right(stl1);
  58. if(pd(stl1,st2)==true)
  59. {
  60. int tfa=findfa(j);
  61. b[i].fa=b[j].fa;
  62. break;
  63. }
  64. //到这代表他们两不适合
  65. }
  66. }
  67. }
  68. for(int i=1;i<=n;i++)
  69. {
  70. for(int j=1;j<=m;j++)
  71. {
  72. if(a[i][j]!=0)
  73. {
  74. int tx=findfa(ll[i][j]);
  75. int ty=ll[i][j];
  76. if(oo[tx]/*代表这个星座是否有字母*/==0)oo[tx]=oo[ty]=++bibi;/*给他们申请一个新的字母*/
  77. else oo[ty]=oo[tx];
  78. printf("%c",oo[ty]+'a'-1);
  79. }
  80. else printf("0");
  81. }
  82. printf("\n");
  83. }

至此,这题就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. extjs 6

    因为最近公司要写一个项目前台所以开始学习extjs前端框架,希望一起共勉. 那么我们的教程就从 Hello World 讲起. helloWorld.js   Ext.onReady(function ...

  2. (十)JavaScript之【DOM定义】

    DOM定义Document Object Model 文档对象模型 是干什么的?改变 HTML 元素的内容 (innerHTML)改变 HTML 元素的样式 (CSS)改变 HTML 元素的属性对 H ...

  3. Ienumerable和Ienumerator的使用

    using UnityEngine; using System.Collections; public class TestCoroutine : MonoBehaviour { void Start ...

  4. 必须夸夸Sublime,大文件打开

    今天有个问题的事情日志文件67.8M大文件打开问题开始: 1.vscode必须挨批:直接就给个错误the file cannt be displayed in the editor because i ...

  5. Linux目录配置——Linux目录配置标准:FHS

    事实上,FHS针对目录树架构仅定义出三层目录下应该放置哪些数据,分别是下面三个目录: 一./(根目录):与开机系统有关 根目录(/)所在分区应该越小越好,且应用程序所安装的软件最好不要与根目录放在同一 ...

  6. shell脚本学习(3)文件判断

    shell常用的文件判断运算符如下: -e 文件是否存在 -f  文件是否是普通文件(不是目录.设备文件.链接文件) -s  表示文件大小不为0 -d 表示文件是否是目录 -b 表示是块设备(光驱.软 ...

  7. IIS7 http自动跳转到https(通过编辑Web.config实现)

    本文摘自:https://www.cnblogs.com/wxbug/p/7054972.html 1.下载安装URL重写模块:Microsoft URL Rewrite Module 32位:htt ...

  8. char 与 signed char 和 unsigned char三者之间的关系

    # char 与 signed char 和 unsigned char三者之间的关系 三者都占用 1个字节,即 8 bit signed char取值范围(-128, 127) unsigned c ...

  9. 木棒,POJ(1011)

    题目链接:http://poj.org/problem?id=1011 解题报告: #include <cstdio> #include <cstring> #include ...

  10. 2017.11.10 web中URL和URI的区别

    URI:Uniform Resource Identifier,统一资源标识符: •URL:Uniform Resource Locator,统一资源定位符: •URN:Uniform Resourc ...