由题意可知,该题的目的是保证有2个X字符的连通块,只能横着或者竖着添加字符,最后寻找最少加几个x字符可以将两个连通块连接起来。
由于该题的数据范围为50*50一共2500个点,所以可以直接枚举。利用dfs将两个连通块分开,表上不同的记号。
然后任意多个将两个连通块连接的x构成的折线等价于这两个点之间的曼哈顿距离-1,所以直接枚举两个连通块之间的点的曼哈顿距离是多少,然后更新最小答案即可。
下面给出,两点间的曼哈顿距离的计算方法:
c++代码参考:
#include<bits/stdc++.h>
using namespace std;
const int N=55;
char ma[N][N]; //存放地图
int vis[N][N];
int n,m;
int px[4]={0,0,1,-1},py[4]={1,-1,0,0};
int mi=1e5;
vector<pair<int,int>>p1,p2;
void dfs(int x,int y,int k) //分别染色两个斑点,放到两个不同的vector数组里
{
if(vis[x][y])return ; //说明染过
vis[x][y]=k;
if(k==1)p1.push_back({x,y});
else p2.push_back({x,y});
for(int i=0;i<4;i++)
{
int ux=x+px[i],uy=y+py[i];
if(ux<1||uy<1||ux>n||uy>m||ma[ux][uy]=='.')continue;
else dfs(ux,uy,k);
}
}
int main()
{
cin>>n>>m;
int k=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>ma[i][j];
//先利用dfs将两个斑点染色
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(ma[i][j]=='X'&&!vis[i][j])
{
dfs(i,j,k);
k++;
}
}
}
for(int i=0;i<p1.size();i++) //暴力枚举两个斑点数组里每个坐标之间的曼哈顿距离-1
{
for(int j=0;j<p2.size();j++)
{
mi=min(mi,abs(p1[i].first-p2[j].first)+abs(p1[i].second-p2[j].second)-1);
}
}
printf("%d",mi);
return 0;
}