一、题目
听说最近两斑点的奶牛最受欢迎,约翰立即购进了一批两斑点牛。
不幸的是,时尚潮流往往变化很快,当前最受欢迎的牛变成了一斑点牛。
约翰希望通过给每头奶牛涂色,使得它们身上的两个斑点能够合为一个斑点,让它们能够更加时尚。
牛皮可用一个 N×M 的字符矩阵来表示,如下所示:
................
..XXXX....XXX...
...XXXX....XX...
.XXXX......XXX..
........XXXXX...
.........XXX....
其中,X 表示斑点部分。
如果两个 X 在垂直或水平方向上相邻(对角相邻不算在内),则它们属于同一个斑点,由此看出上图中恰好有两个斑点。
约翰牛群里所有的牛都有两个斑点。
约翰希望通过使用油漆给奶牛尽可能少的区域内涂色,将两个斑点合为一个。
在上面的例子中,他只需要给三个 .. 区域内涂色即可(新涂色区域用 ∗ 表示):
................
..XXXX....XXX...
...XXXX*...XX...
.XXXX..**..XXX..
........XXXXX...
.........XXX....
请帮助约翰确定,为了使两个斑点合为一个,他需要涂色区域的最少数量。
输入格式
第一行包含两个整数 N 和 M。
接下来 N 行,每行包含一个长度为 M 的由 X 和 .. 构成的字符串,用来表示描述牛皮图案的字符矩阵。
输出格式
输出需要涂色区域的最少数量。
数据范围
1≤N,M≤50
输入样例:
6 16
................
..XXXX....XXX...
...XXXX....XX...
.XXXX......XXX..
........XXXXX...
.........XXX....
输出样例:
3
二、题目分析
分析
根据题意来看很容易判断出可以用dfs或bfs来解决,我是选用的dfs。
首先,题目中明确说明了,约翰牛群里所有的牛都有两个斑点,即有两量组不连通的X。题目要求是求涂色区域的最少数量。很容易看出,最少数量=两边X之间的最小的曼哈顿距离-1(二维空间,曼哈顿距离d = |x1 - x2| + |y1 - y2|),所以题目转变为去求曼哈顿距离。
那我们可以定义两个容器,分别存放两组X的坐标。而后遍历两组坐标,求出最小的曼哈顿距离。
步骤1
dfs将两组X坐标分别放入两个容器
步骤2
遍历容器求最小的曼哈顿距离
步骤3
给求到的最小曼哈顿距离-1并输出
三、代码
#include<bits/stdc++.h>
using namespace std;
const int N=60;
char a[N][N];
typedef pair<int,int>pii;
vector<pii> p[2];//存放两组X的坐标
int n,m;
int dx[4]={0,0,1,-1};//偏移量,即在搜索过程中,控制坐标只能在上下左右移动一个单位
int dy[4]={1,-1,0,0};
bool check(int x,int y){//判断坐标是否越界
if(x>n||y>m||x<1||y<1) return false;
else return true;
}
void dfs(int x,int y,vector<pii> &pp){
if(!check(x,y)) return ;
if(a[x][y]=='.') return ;
else{
a[x][y]='.';//把X变成.这样在主函数的双重循环中,dfs只会进入两次,每一次都会把一组X坐标存入,并且把这一组的X全变为.
pp.push_back({x,y});
for(int i=0;i<4;i++){
int tx=x+dx[i],ty=y+dy[i];
dfs(tx,ty,pp);
}
}
}
int main(){
int k=0;//表示使用的是第几个容器,因为只有两组X,所以k的值只会是0,1
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]=='X'){
dfs(i,j,p[k++]);
}
}
}
int ans=120;//存放最小曼哈顿距离,初始化值必须大于左上的坐标与右下坐标的曼哈顿距离,即大于98
for(int i=0;i<p[0].size();i++){
for(int j=0;j<p[1].size();j++){
ans=min(ans,(abs(p[0][i].first-p[1][j].first)+abs(p[0][i].second-p[1][j].second)));//求曼哈顿距离,并与当前最小值比较
}
}
cout<<ans-1;
}