【AcWing】蓝桥杯集训每日一题Day16|哈希|FloodFill算法|字典序最小|映射|1402.星空之夜(C++)

1402.星空之夜
1402. 星空之夜 - AcWing题库
难度:中等
时/空限制:1s / 64MB
总通过数:3415
总尝试数:7434
来源:

usaco training 5.1
算法标签

Flood Fill哈希DFSBFS

题目内容

夜空深处,闪亮的星星以星群的形式出现在人们眼中,形态万千。
一个星群是指一组非空的在水平,垂直或对角线方向相邻的星星的集合。
一个星群不能是一个更大星群的一部分。
星群可能是相似的。
如果两个星群的形状、包含星星的数目相同,那么无论它们的朝向如何,都认为它们是相似的。
通常星群可能有 8 种朝向,如下图所示:
starry-1.gif
现在,我们用一个二维 01 矩阵来表示夜空,如果一个位置上的数字是 1,那么说明这个位置上有一个星星,否则这个位置上的数字应该是 0。
给定一个夜空二维矩阵,请你将其中的所有星群用小写字母进行标记,标记时相似星群用同一字母,不相似星群用不同字母。
标注星群就是指将星群中所有的 1 替换为小写字母。

输入格式

第一行包含一个整数 W,表示矩阵宽度。
第二行包含一个整数 H,表示矩阵高度。
接下来 H 行,每行包含一个长度为 W 的 01 序列,用来描述整个夜空矩阵。

输出格式

输出标记完所有星群后的二维矩阵。
用小写字母标记星群的方法很多,我们将整个输出读取为一个字符串,能够使得这个字符串字典序最小的标记方式,就是我们想要的标记方式。
输出这个标记方式标出的最终二维矩阵。

数据范围

0≤W,H≤100,
0≤ 星群数量 ≤500,
0≤ 不相似星群数量 ≤26,
1≤ 星群中星星的数量 ≤160

输入样例:
23
15
10001000000000010000000
01111100011111000101101
01000000010001000111111
00000000010101000101111
00000111010001000000000
00001001011111000000000
10000001000000000000000
00101000000111110010000
00001000000100010011111
00000001110101010100010
00000100110100010000000
00010001110111110000000
00100001110000000100000
00001000100001000100101
00000001110001000111000
输出样例:
a000a0000000000b0000000
0aaaaa000ccccc000d0dd0d
0a0000000c000c000dddddd
000000000c0b0c000d0dddd
00000eee0c000c000000000
0000e00e0ccccc000000000
b000000e000000000000000
00b0f000000ccccc00a0000
0000f000000c000c00aaaaa
0000000ddd0c0b0c0a000a0
00000b00dd0c000c0000000
000g000ddd0ccccc0000000
00g0000ddd0000000e00000
0000b000d0000f000e00e0b
0000000ddd000f000eee000
样例解释

样例对应的星空图如下:
starry-2.gif
答案对应的标记后星空图如下:
starry-3.gif

题目解析

给一个矩阵,表示夜空,用黑色的块表示星星,连通块是八连通,只要有公共的边和点,都算连通
每一个连通块都算一个星群,星群里面有八种朝向,通过旋转和对称得到的这八种朝向是等价的
矩阵的形式是01二维矩阵,0表示空,1表示有星星
找出其中所有相同的星群,要把所有的星群归类,相同的归为一类,不同的归为另外一类
同一类星群用同一个小写英文字母标记,不同的星群用不同的英文小写字母标记

矩阵最大的长宽是100x100
星群数量最大是500
不相同的星群数量不会超过26个,一定可以用26个英文字母全部标记出来
标记的时候,是把星群用对应的字母替换掉,同一种星群用同一个字母替换
输出的时候,标记的方案有很多种,为了方便评测,规定输出一个字典序最小的方案,就是把每一行拼接起来,拼成一个字符串

1. 怎么去找一个星群

找一个星群就是找连通块,可以用Flood Fill算法,BFS、DFS或并查集,把所有连通块找出来

2. 如何区分星群

因为数据范围比较小,最多只会包含500个星群,每个星群中最多只会包含160个星星
可以使用暴力的方式去找,可以把星群所有出现的坐标存到一个数组里,每一次拿到一个新的星群之后,判断一下它在存过的星群里面有没有出现过,一个一个去比一遍,出现过的话,就是同一类,没有出现过的话,就是一种全新的类,时间复杂度是 O ( 500 ∗ 26 ∗ 160 ) O(500*26*160) O(50026160),真实情况会比这个小很多
用暴力的方法比较,把八种朝向都枚举一遍,x8,最多1664万的计算量,可以过

[!NOTE] 如何优化
字符串哈希
因为只需要辨别是相同还是不同
把很多星群的所有信息,想办法把每一个星群,把它映射到一个数,再去判断这个数在前面有没有出现过

  1. 如何把星群转化成数
    和字符串哈希一样,字符串哈希是把字符串转化成一个数,不能保证不冲突,有可能把不同形状的星群映射到同一个数,可以选择一种出现这种情况概率极低的一种哈希方式
    这类算法不能保证一定是正确的,但是可以保证99%是正确的,不是精确算法,但是可以认为基本上是精确的
    如字符串哈希,哈希值不一样,原字符串一定一样,哈希值一样,原字符串不一定一样,但是大概率是一样的
    包括快排和哈希表
  • 快排在平均意义上是nlogn,极限情况下时间复杂度是n^2,但是可以认为极限情况很难出现,
  • 哈希表均摊是O(1)的,极端情况下也可以产生O(n)
  1. 怎么哈希
    这个哈希方法应该尽量让它对旋转和对称是不敏感的,就是不管是旋转还是对称都不影响哈希值,
    计算星群当中两个点两两之间,比如总共有k个点,就有 C k 2 C_{k}^2 Ck2种关系,每两个点之间的欧几里得距离,直线距离的总和
    这种哈希方式是比较好的,如果是曼哈顿距离的话,冲突的概率更大

如果这种哈希方法答案错误的话,可以提供两个哈希值,哈希值1,就是计算一下直线距离的总和,再用另外一个哈希函数,两个哈希函数都判错的情况就比较低了

通过这样的哈希方式可以将星群映射成一个浮点数,还会去除掉旋转和对称的影响

整个图做一遍,包含1万个点,计算量是1万;星群最多是500个,每个星群枚举一遍,比较26次,是两万多的计算量

3. 如何保证字典序最小

对于大部分问题,要求字典序最小都不会增加题目的难度,主要是为了方便评测
从第一行开始枚举,当找到第一个1的时候,就把第一个1所在的连通块找出来,给这个连通块赋一个什么字母
出现过的话,赋出现过的字母
没有出现过的话,赋当前没有出现过的最小的字母
当前没有出现过的字母如果是a的话,是按照字符串的顺序一个一个枚举的,当前字母选a的话,一定比选大于a的字母的字典序更小
所以从前往后找的时候,如果发现了一个新的星群,就从小到大赋字母,这样可以保证字典序是最小的

比较浮点数是不是相等的时候,需要考虑精度(参考上一篇)

代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 110, M = 170;
const double eps = 1e-8;

int n, m;
char g[N][N];
PII q[M];    //用pair数组存所有的星群的坐标
int top = 0; //当前星群星星的数量
double hash_val[30]; //把前面所有出现过的星群的哈希值都存下来
int cnt = 0;  //当前不同星群的数量

void dfs(int a, int b)
{
	//先把当前的星星存下来
	q[top ++] = {a, b};
	//已经搜过的话,标记为0
	g[a][b] = '0';

	//枚举一下周围八个方向
	for (int x = a - 1; x <= a + 1; x ++)
		for (int y = b - 1; y <= b + 1; y ++)
			//如果发现当前的下标没有越界,并且当前的位置是1
			if (x >= 0 && x < n && y >= 0 && y < m && g[x][y] == '1')
				dfs(x, y);
}

double get_dist(PII& a, PII& b)
{
	//先求一下坐标之差
	double dx = a.x - b.x, dy = a.y - b.y;
	return sqrt(dx * dx + dy * dy);
}

double get_hash()
{
	double sum = 0;
	//等于所有点对之间的距离之和
	for (int i = 0; i < top; i ++)
		for (int j = 0; j < i; j ++)
			sum += get_dist(q[i], q[j]);
	return sum;
}

char get_id()
{
	//先求当前星群的哈希值
	double val = get_hash();
	//判断之前有没有出现过
	for (int i = 0; i < cnt; i ++)
		if (abs(hash_val[i] - val) < eps)
			return 'a' + i;
	//如果没有出现过,存下来
	hash_val[cnt ++] = val;
	return 'a' + cnt - 1;
}

int main()
{
	//读入m和n
	scanf("%d%d", &m, &n);
	//读入整个矩阵
	for (int i = 0; i < n; i ++) scanf("%s", g[i]);

	//从前往后依次枚举每一个位置
	for (int i = 0; i < n; i ++)
		for (int j = 0; j < m; j ++)
			//如果发现当前的位置是1的话,表示发现了一个新的星群
			if (g[i][j] == '1')
			{
				top = 0;  //先把top清空
				dfs(i, j); //floodfill 把所有和i,j连通的星星找出来
				//求一下当前星群的id
				char id = get_id();

				//把所有的格子赋成id
				for (int k = 0; k < top; k ++)
					g[q[k].x][q[k].y] = id;
			}
	//输出整个矩阵
	for (int i = 0; i < n; i ++) puts(g[i]);
	//puts等价于printf %s\n
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/530752.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring Cloud系列(二):Eureka Server应用

系列文章 Spring Cloud系列(一)&#xff1a;Spirng Cloud变化 Spring Cloud系列(二)&#xff1a;Eureka Server应用 目录 前言 注册中心对比 Nacos Zookeeper Consul 搭建服务 准备 搭建 搭建父模块 搭建Server模块 启动服务 测试 其他 前言 前面针对新版本的变化有了…

Linux--进程的概念(二)

目录 一、进程的优先级1.1 基本概念1.2 查看进程优先级1.3 PRI&NI1.4 如何更改进程的优先级1.4.1 用top命令更改进程的nice1.4.2 用renice命令更改进程的nice 1.5 其他概念 二、环境变量2.1 基本概念2.2 常见的环境变量2.3 查看环境变量2.3.1 测试PATH2.3.2 测试HOME2.3.3 …

安全操作代码优化思路

理论依据 数据增强和样本选择 在训练阶段&#xff0c;您可以考虑添加数据增强来提升模型的鲁棒性和泛化能力。针对人脸检测任务&#xff0c;可以尝试以下改进&#xff1a; 对输入图像进行随机裁剪、缩放、旋转、翻转等数据增强操作&#xff0c;以增加数据的多样性。 使用难样…

【堡垒机】堡垒机的介绍

目前&#xff0c;常用的堡垒机有收费和开源两类。 收费的有行云管家、纽盾堡垒机&#xff1b; 开源的有jumpserver&#xff1b; 这几种各有各的优缺点&#xff0c;如何选择&#xff0c;大家可以根据实际场景来判断 什么是堡垒机 堡垒机&#xff0c;即在一个特定的网络环境下&…

革命性突破:Stability AI发布全新12B参数Stable LM 2模型,颠覆AI界!

Stability AI已推出其Stable LM 2语言模型系列的最新成员&#xff1a;一个120亿参数的基础模型和一个经过指令调优的变体。这些模型在七种语言上训练&#xff0c;包括英语、西班牙语、德语、意大利语、法语、葡萄牙语和荷兰语&#xff0c;训练数据达到了令人印象深刻的两万亿个…

JavaScript(1)神秘的编程技巧

大家都感兴趣的箭头函数 箭头函数在许多场景中都可以发挥作用&#xff0c;尤其适用于简化函数声明和提高代码的可读性。以下是箭头函数可以使用的一些常见方面&#xff1a; &#xff08;1&#xff09;回调函数&#xff1a; 箭头函数特别适合作为回调函数&#xff0c;例如在事…

【教程】App打包成IPA文件类型的四种方法

摘要 本教程总结了将App应用程序打包为IPA包的四种常用方法&#xff0c;包括Apple推荐的方式、iTunes拖入方法、自动编译脚本和解压改后缀名方法。每种方法都有其特点和适用场景&#xff0c;在实际开发中可以根据需求选择合适的方式进行打包。通过本教程&#xff0c;您将了解到…

微服务(狂神)

什么是微服务&#xff1a; 微服务方案&#xff1a; 1. SpringCloud NetFlix 2. Dubbo 3. SpringCloud Alibaba 解决了什么问题&#xff1a; 1. 服务过多&#xff0c;客户端怎么访问 2. 服务过多&#xff0c;服务间怎么传值 3. 服务过多&#xff0c;如何治理 4. 服务过多…

【随笔】Git 高级篇 -- 最近标签距离查询 git describe(二十一)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

JVM基础第一篇

内存结构 程序计数器 1.定义 在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;每个线程都有一个独立的程序计数器&#xff0c;它是线程私有的&#xff0c;不会被线程切换所影响。 2.作用 记住下一条jvm指令的执行地址 3.特点 是线程私有的不会存在内存溢出 虚拟机…

nginx配置证书和私钥进行SSL通信验证

文章目录 一、背景1.1 秘钥和证书是两个东西吗&#xff1f;1.2 介绍下nginx配置文件中参数ssl_certificate和ssl_certificate_key1.3介绍下nginx支持的证书类型1.4 目前nginx支持哪种证书格式&#xff1f;1.5 nginx修改配置文件目前方式也会有所不同1.6 介绍下不通格式的证书哪…

【DM8】序列

创建序列 图形化界面创建 DDL CREATE SEQUENCE "TEST"."S1" INCREMENT BY 1 START WITH 1 MAXVALUE 100 MINVALUE 1;参数&#xff1a; INCREMENT BY < 增量值 >| START WITH < 初值 >| MAXVALUE < 最大值 >| MINVALUE < 最小值…

Proxmox VE qm 方式一键创建Windows虚拟机

前言 实现qm 方式一键创建Windows虚拟机&#xff0c;提高效率。 qm 一键创建Windows虚拟机 以下实现在线下载镜像&#xff0c;创建虚拟机&#xff0c;安装系统需要自己手动安装哦&#xff0c;如果想实现全自动安装系统&#xff0c;建议部署自己的内网pxe server 系统参考各参…

Utilize webcam to capture photo with camera

1. Official Guide& my github Official course my github 2. Overcome Webcam js Error in Chrome: Could not access webcam link 直接把代码拷贝到本机的下述目录下 To ignore Chrome’s secure origin policy, follow these steps. Navigate to chrome://flags/#un…

【前端捉鬼记】使用nvm切换node版本后再用node -v查看仍然是原来的版本

今天遇到一个诡异的问题&#xff0c;使用nvm切换node版本&#xff0c;明明提示已经切换成功&#xff0c;可是再次查看node版本还是之前的&#xff01; 尝试了很多办法&#xff0c;比如重新打开一个cmd窗口、切换前执行nvm install version都没成功&#xff0c;直到找到这篇文章…

【计算机毕业设计】企业仓储管理系统——后附源码

&#x1f389;**欢迎来到我的技术世界&#xff01;**&#x1f389; &#x1f4d8; 博主小档案&#xff1a; 一名来自世界500强的资深程序媛&#xff0c;毕业于国内知名985高校。 &#x1f527; 技术专长&#xff1a; 在深度学习任务中展现出卓越的能力&#xff0c;包括但不限于…

【算法】双指针算法

个人主页 &#xff1a; zxctscl 如有转载请先通知 题目 1. 283. 移动零1.1 分析1.2 代码 2. 1089. 复写零2.1 分析2.2 代码 3. 202. 快乐数3.1 分析3.2 代码 4. 11. 盛最多水的容器4.1 分析4.2 代码 5. LCR 179. 查找总价格为目标值的两个商品5.1 分析5.2 代码 6. 15. 三数之和…

【攻防世界】web2(逆向解密)

进入题目环境&#xff0c;查看页面信息&#xff1a; <?php $miwen"a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws";function encode($str){$_ostrrev($str);// echo $_o;for($_00;$_0<strlen($_o);$_0){$_csubstr($_o,$_0,1);$__ord($_c)1;…

2014最新AI智能系统ChatGPT网站源码GPTs应用支持+Ai绘画网站源码+搭建部署教程文档

一、文章前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支持…

深度解析SPARK的基本概念

关联阅读博客文章&#xff1a; 深入理解MapReduce&#xff1a;从Map到Reduce的工作原理解析 引言&#xff1a; 在当今大数据时代&#xff0c;数据处理和分析成为了企业发展的重要驱动力。Apache Spark作为一个快速、通用的大数据处理引擎&#xff0c;受到了广泛的关注和应用。…