最少联通代价【曼哈顿距离】

2023-11-09 08:30

本文主要是介绍最少联通代价【曼哈顿距离】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

在一个 N 行 M 列的字符网格上, 恰好有 2 个彼此分开的连通块。每个连通 块的一个格点与它的上、下、左、右的格子连通。如下图所示:

现在要把这 2 个连通块连通, 求最少需要把几个’.’转变成’X’。上图的例子中, 最少只需要把 3个’.’转变成’X’。下图用’*’表示转化为’X’的格点。

Input

第 1 行:2 个整数 N 和 M(1<=N,M<=50) 接下来 N 行,每行 M 个字符, ’X’表示属于某个连通块的格点,’.’表示不属于某 个连通块的格点

Output

第 1 行:1 个整数,表示最少需要把几个’.’转变成’X’

Sample Input

6 16
…………….
..XXXX….XXX…
…XXXX….XX…
.XXXX……XXX..
……..XXXXX…
………XXX….

Sample Output

3


思路简析

法一:先用一个小深搜区分出两个连通块的点,再用广搜搜出每个连通块1的点到每个连通块2的点上的距离,每次用min()更新最小值。
代码实现如下(找的一位Pal帮忙打的,还是有点儿良心特此声明):

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,pre[1000000],a[1000000],b[1000000],minn,ans=1e10;
int x[4]={1,-1,0,0},y[4]={0,0,1,-1};
char map[100][100];
bool mark[100][100];
bool check(int s,int t)
{if(s&&t&&s<=n&&t<=m&&!mark[s][t]&&map[s][t]!='S') return 1;return 0;
}
void fun(int d)
{minn++;if(pre[d]) fun(pre[d]);
}
void bfs(int r,int c)
{memset(mark,0,sizeof(mark));minn=0;int head=0,tail=1;int nextr,nextc;mark[r][c]=1;pre[1]=0;a[1]=r;b[1]=c;while(head!=tail){head++;for(int i=0;i<4;i++){nextr=a[head]+x[i];nextc=b[head]+y[i];if(check(nextr,nextc)){tail++;a[tail]=nextr;b[tail]=nextc;mark[nextr][nextc]=1;pre[tail]=head;if(map[nextr][nextc]=='X'){fun(tail);ans=min(minn,ans);}}}}
}
void dfs(int r,int c)
{for(int i=0;i<4;i++)if(check(r+x[i],c+y[i])&&map[r+x[i]][c+y[i]]!='.'){mark[r+x[i]][c+y[i]]=1;map[r+x[i]][c+y[i]]='S';dfs(r+x[i],c+y[i]);mark[r+x[i]][c+y[i]]=0;}
}
void f()
{for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(map[i][j]=='X'){dfs(i,j);map[i][j]='S';return ;}
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%s",map[i]+1);bool flag=1;f();for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(map[i][j]=='S')bfs(i,j);printf("%d",ans-2);
}

法二:也同样用一个小深搜,记录下两个连通块分别的各自坐标,再用曼哈顿距离的思想枚举每个连通块1上的点到每个连通块2上的点上的距离,求出最小值。
干货:详解曼哈顿距离及其代替广搜的原因
但这道题应是曼哈顿距离-1,因为它并不是要求路径步数,而是求联通代价,当距离第二个连通块还剩一步的时候,就已经达成目标了,不用走到第二个连通块上去,所以要少一步。
代码实现如下:

#include<cstdio>
#include<cmath>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
char a[55][55];//存“地图”
int n,m/*长、宽*/,ans=1e8/*顾名思义*/,xx[4]={-1,0,0,1},yy[4]={0,-1,1,0}/*移动方向*/,s/*表示现在搜到的是第几个连通块*/;
struct node{int x1,y1;
}temp;//结构体记录下坐标,temp用来将坐标存入结构体,放进数组
vector<node>f[2];//由于不确定连通块1、2分别有多少个点,所以用动态数组存储//其实很简单,待会儿结尾放一个超链接
void dfs(int x, int y)
{a[x][y]='.';//避免重复搜索temp.x1=x;temp.y1=y;f[s].push_back(temp);//记录坐标,放进数组里for(int i=0;i<4;i++)//拓展四周联通的连通块点做处理{int fx=x+xx[i],fy=y+yy[i];if(fx>=0&&fx<n&&fy>=0&&fy<m&&a[fx][fy]=='X')dfs(fx,fy);}
}
int main()
{scanf("%d %d",&n,&m);for(int i=0;i<n;i++)scanf("%s",a[i]);//读取一行字符
/*忽然想到补充一点,如果从[1]开始的话,应该这么写:for(int i=1;i<=n;i++)scanf("%s",a[i]+1);a[i]就是地址,+1就是往后一个存(数组的地址是连续的)
*/for(int i=0;i<n;i++)for(int j=0;j<m;j++)if(a[i][j]=='X')//搜到一个连通块{dfs(i,j);s++;//连通块+1}for(int i=0;i<f[0].size();i++)for(int j=0;j<f[1].size();j++)ans=min(ans,int(fabs(f[0][i].x1-f[1][j].x1)+fabs(f[0][i].y1-f[1][j].y1)-1));//利用曼哈顿距离思想求解printf("%d",ans);return 0;
}

这篇关于最少联通代价【曼哈顿距离】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

✨机器学习笔记(二)—— 线性回归、代价函数、梯度下降

1️⃣线性回归(linear regression) f w , b ( x ) = w x + b f_{w,b}(x) = wx + b fw,b​(x)=wx+b 🎈A linear regression model predicting house prices: 如图是机器学习通过监督学习运用线性回归模型来预测房价的例子,当房屋大小为1250 f e e t 2 feet^

线性代数|机器学习-P35距离矩阵和普鲁克问题

文章目录 1. 距离矩阵2. 正交普鲁克问题3. 实例说明 1. 距离矩阵 假设有三个点 x 1 , x 2 , x 3 x_1,x_2,x_3 x1​,x2​,x3​,三个点距离如下: ∣ ∣ x 1 − x 2 ∣ ∣ 2 = 1 , ∣ ∣ x 2 − x 3 ∣ ∣ 2 = 1 , ∣ ∣ x 1 − x 3 ∣ ∣ 2 = 6 \begin{equation} ||x

模拟退火求n个点到某点距离和最短

/*找出一个点使得这个店到n个点的最长距离最短,即求最小覆盖圆的半径用一个点往各个方向扩展,如果结果更优,则继续以当前步长扩展,否则缩小步长*/#include<stdio.h>#include<math.h>#include<string.h>const double pi = acos(-1.0);struct point {double x,y;}p[1010];int

黑神话:悟空》增加草地绘制距离MOD使游戏场景看起来更加广阔与自然,增强了游戏的沉浸式体验

《黑神话:悟空》增加草地绘制距离MOD为玩家提供了一种全新的视觉体验,通过扩展游戏中草地的绘制距离,增加了场景的深度和真实感。该MOD通过增加草地的绘制距离,使游戏场景看起来更加广阔与自然,增强了游戏的沉浸式体验。 增加草地绘制距离MOD安装 1、在%userprofile%AppDataLocalb1SavedConfigWindows目录下找到Engine.ini文件。 2、使用记事本编辑

【每日一题】LeetCode 2379.得到K个黑块的最少涂色次数(字符串、滑动窗口)

【每日一题】LeetCode 2379.得到K个黑块的最少涂色次数(字符串、滑动窗口) 题目描述 给定一个字符串 blocks,其中每个字符代表一个颜色块,可以是 ‘W’(白色)或 ‘B’(黑色)。你需要找到一个至少包含 k 个连续黑色块的子串。每次操作可以将一个白色块变成黑色块。你的任务是找到至少出现一次连续 k 个黑色块的最少操作次数。 和该题目类似:【每日一题】LeetCode 202

【造轮子】纯C++实现的联通组件标记算法

学习《OpenCV应用开发:入门、进阶与工程化实践》一书 做真正的OpenCV开发者,从入门到入职,一步到位! 连接组件标记算法 连接组件标记算法(connected component labeling algorithm-CCL)是图像分析中最常用的算法之一,算法的实质是扫描一幅图像的每个像素,对于像素值相同的分为相同的组(group),最终得到图像中所有的像素连通组件。扫描的方式可以是从

SimD:基于相似度距离的小目标检测标签分配

摘要 https://arxiv.org/pdf/2407.02394 由于物体尺寸有限且信息不足,小物体检测正成为计算机视觉领域最具挑战性的任务之一。标签分配策略是影响物体检测精度的关键因素。尽管已经存在一些针对小物体的有效标签分配策略,但大多数策略都集中在降低对边界框的敏感性以增加正样本数量上,并且需要设置一些固定的超参数。然而,更多的正样本并不一定会带来更好的检测结果,事实上,过多的正样本

Matlab)实现HSV非等间隔量化--相似判断:欧式距离--输出图片-

%************************************************************************** %                                 图像检索——提取颜色特征 %HSV空间颜色直方图(将RGB空间转化为HS

智力题:25匹马5条跑道找最快的3匹马,最少需要跑几次?

要找出25匹马中最快的3匹马,使用5条跑道,最少需要跑几次?我们可以通过逐步推理来解决这个问题。 第一步:分组比赛 首先,我们将25匹马分成5组,每组5匹马。每组进行一次比赛,这样我们就有5次比赛的结果。 组1:A1, A2, A3, A4, A5 组2:B1, B2, B3, B4, B5 组3:C1, C2, C3, C4, C5 组4:D1, D2, D3, D4, D5 组

C/C++两点坐标求距离以及C++保留两位小数输出,秒了

目录 1. 前言 2. 正文 2.1 问题 2.2 解决办法 2.2.1 思路 2.2.2 代码实现 3. 备注 1. 前言 依旧是带来一个练手的题目,目的就一个,方法千千万,通向终点的方式有很多种,没有谁与谁,我们都是为了成为更好的自己。 2. 正文 2.1 问题 题目描述: 输入两点坐标(X1,Y1),(X2,Y2),计算并输出两点间的距离。 输入格式: