牛客小白月赛——图像存储(BFS+去重)

2024-04-25 00:48

本文主要是介绍牛客小白月赛——图像存储(BFS+去重),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

图像存储

这道题是学校训练赛遇到的,困扰了许久,最终在网上找到这一种较为简单且容易实现的。除了这一种解法还有其他的比如二维哈希,这里只讲BFS+去重的方法 其实因为其他的都不会
先上链接:图像存储
首先若是不考虑题中的第二个问题,图像中黑块的种类,单单只询问图中的黑块数目。是不是很简单,只需要循环寻找每一个黑点(即数字1)sum++。然后以此为起点跑一遍bfs寻找出所有和这一黑点连在一块的黑点,将其置为0即可(或者用vis[][]保存遍历过的点)。

char arr[N][N];
int dx[5]={1,0,-1,0};
int dy[5]={0,1,0,-1};
for(i=0;i<n;i++)
{for(j=0;j<m;j++){if(arr[i][j]=='1'){sum++;//因为bfs时会将找到的整个图像块置为0,所以不会有重复计数bfs(i,j);}}
}
void bfs(int si,int sj)//用bfs寻找图像块//非完整代码,部分注释不符合代码继续往下看即可
{//因为查找顺序都是基于dx,dy数组,所以存入vector的点的都是以相同的顺序int r,c,row,col,k,Min1=si,Min2=sj;queue <node>q;   q.push({si,sj});arr[si][sj]=0;//因为有将找过的点重置0的操作所以不需要vis数组来进行判断while(!q.empty()){node t=q.front();q.pop();row=t.first, col=t.second;for(k=0;k<4;k++){r=row+dy[k], c=col+dx[k];if(r>=0&&r<n&&c>=0&&c<m&&arr[r][c]=='1'){arr[r][c]='0';q.push({r,c});}}}
}

而这个题目的难点在于问题二:如何判断每次遍历出的图像是否之前已经出现过。

因为我们使用for循环自上而下,自左而右寻找新的黑块,每次寻找到一定会是这个黑块的最上面的点(不一定是最右边的点),并且bfs时是以固定的顺序遍历,比如左、右、上、下,或者其他顺序,总之若是两个相同的黑块尽管在矩阵中的位置不同,遍历时找到各个点的顺序是不会变的。
那么我们储存黑块信息时就可以选择用pair来记录点(pair<int,int>分别代表在矩阵中该点的横纵坐标),将所有点都用vector来储存,那么vector里面就可以把这个黑块的信息存下。最后再用set存这些vector来实现去重。

typedef pair<int,int>node;
typedef vector<node> G;
set<G> shapes;//用set容器去重,set容器自带对pair的函数比较,若要使用结构体则要重载函数

最后还有一个重要的问题,你可能会发现还有一个巨大的bug,虽然相同的黑块点遍历顺序一样,但点的坐标不一样呀,set去重何从谈起?那么我们把所有的黑块移动到矩阵左上角不就行了吗,相同的黑块若都移动到矩阵左上角不就可以去重了吗。
实现:在bfs时遍历每个点时,记录这个黑块的所有点的行数最小值和列数最小值,然后循环保存有所有点的vector容器,将所有点的row -= minrow,col -= mincol.
最终vector里的黑块就是移动到矩阵左上角的情况。
补充一点:有大佬山鸡哥指出,并不一定要找minrow与mincol,直接以找到的第一个点的横纵坐标去移动也是可以的,因为是用点集来表示黑块,所以不用担心减成负数,最后的相同的图像肯定会移动到重合的。

完整代码:

#include<set>
#include<queue>
#include<utility>
#include<vector>
#include<stdio.h>
#include<string.h>
using namespace std;
#define N 1005
int n,m,ans;
char arr[N][N];
int dx[5]={1,0,-1,0};
int dy[5]={0,1,0,-1};
typedef pair<int,int>node;
typedef vector<node> G;
set<G> shapes;//用set容器去重,set容器自带对pair的函数比较,若要使用结构体则要重载函数void bfs(int si,int sj)//用bfs寻找图像块
{//因为查找顺序都是基于dx,dy数组,所以存入vector的点的都是以相同的顺序int r,c,row,col,k,Min1=si,Min2=sj;queue <node>q;   q.push({si,sj});vector<node>g;	 g.push_back({si,sj});arr[si][sj]=0;//因为有将找过的点重置0的操作所以不需要vis数组来进行判断while(!q.empty()){node t=q.front();q.pop();row=t.first, col=t.second;for(k=0;k<4;k++){r=row+dy[k], c=col+dx[k];if(r>=0&&r<n&&c>=0&&c<m&&arr[r][c]=='1'){arr[r][c]='0';q.push({r,c});g.push_back({r,c});//去重的关键,两个Min,分别存此图像块的最上点和最左点Min1 = min(Min1,r);Min2 = min(Min2,c);}}}//去重操作:将所有点的坐标减去两个最小值,可以理解为将所有图像移动到左上角来进行判重的比较for(k=0;k<g.size();k++){g[k].first  -= Min1;g[k].second -= Min2;}if(!shapes.count(g)){shapes.insert(g);}
}int main()
{int i,j,sum;while(scanf("%d %d",&n,&m)){if(n==0)break;for(i=0;i<n;i++){scanf("%s",arr[i]);	}shapes.clear();//记得清空setsum=0, ans=0;for(i=0;i<n;i++){for(j=0;j<m;j++){if(arr[i][j]=='1'){sum++;//因为bfs时会将找到的整个图像置为0,所有不会有重复计数bfs(i,j);}}}ans=shapes.size();printf("%d %d\n",sum,ans);}return 0;
}

本算法学自这位大佬的博客:【牛客比赛】牛客小白月赛31
嗯,对其稍作解释,表达我粗劣的看法,若有错误请在评论区指正。可能因为懒,而懒得改,耶

这篇关于牛客小白月赛——图像存储(BFS+去重)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/933300

相关文章

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

HDFS—存储优化(纠删码)

纠删码原理 HDFS 默认情况下,一个文件有3个副本,这样提高了数据的可靠性,但也带来了2倍的冗余开销。 Hadoop3.x 引入了纠删码,采用计算的方式,可以节省约50%左右的存储空间。 此种方式节约了空间,但是会增加 cpu 的计算。 纠删码策略是给具体一个路径设置。所有往此路径下存储的文件,都会执行此策略。 默认只开启对 RS-6-3-1024k

hdu1254(嵌套bfs,两次bfs)

/*第一次做这种题感觉很有压力,思路还是有点混乱,总是wa,改了好多次才ac的思路:把箱子的移动当做第一层bfs,队列节点要用到当前箱子坐标(x,y),走的次数step,当前人的weizhi(man_x,man_y),要判断人能否将箱子推到某点时要嵌套第二层bfs(人的移动);代码如下:

poj 2195 bfs+有流量限制的最小费用流

题意: 给一张n * m(100 * 100)的图,图中” . " 代表空地, “ M ” 代表人, “ H ” 代表家。 现在,要你安排每个人从他所在的地方移动到家里,每移动一格的消耗是1,求最小的消耗。 人可以移动到家的那一格但是不进去。 解析: 先用bfs搞出每个M与每个H的距离。 然后就是网络流的建图过程了,先抽象出源点s和汇点t。 令源点与每个人相连,容量为1,费用为

POJ 3057 最大二分匹配+bfs + 二分

SampleInput35 5XXDXXX...XD...XX...DXXXXX5 12XXXXXXXXXXXXX..........DX.XXXXXXXXXXX..........XXXXXXXXXXXXX5 5XDXXXX.X.DXX.XXD.X.XXXXDXSampleOutput321impossible

速了解MySQL 数据库不同存储引擎

快速了解MySQL 数据库不同存储引擎 MySQL 提供了多种存储引擎,每种存储引擎都有其特定的特性和适用场景。了解这些存储引擎的特性,有助于在设计数据库时做出合理的选择。以下是 MySQL 中几种常用存储引擎的详细介绍。 1. InnoDB 特点: 事务支持:InnoDB 是一个支持 ACID(原子性、一致性、隔离性、持久性)事务的存储引擎。行级锁:使用行级锁来提高并发性,减少锁竞争

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

深度优先(DFS)和广度优先(BFS)——算法

深度优先 深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支,当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访

Verybot之OpenCV应用一:安装与图像采集测试

在Verybot上安装OpenCV是很简单的,只需要执行:         sudo apt-get update         sudo apt-get install libopencv-dev         sudo apt-get install python-opencv         下面就对安装好的OpenCV进行一下测试,编写一个通过USB摄像头采