传送门
这道题其实思想不是很难
就是给你一个有三个连通块的矩阵,让你染最少的点让着三个连通块连起来
看到题意,加上
大声喊出:
爆搜!
有几个数组
表示
属于哪个连通块
表示
到第
个连通块的最短距离
表示第
个连通块到第
个连通块的距离
首先我们先
将三个连通块染色,复杂度
然后我们
预处理每一个点到不同连通块的最短距离,扫描起点
,每个点扫一遍加起来
然后我们求出每个连通块的最短距离
那么答案就是
收工
但是这样写交上去只有66分
为什么呢?
我们考虑着三个连通块最后连到一起的路径,可能是这样的
1-------3
|
|
2
也就是我们之前算的那种情况
但也有可能是这样的
1
|
K--------3
|
2
就是三个连通块连向同一个点
这个时候我们再按上面那种做法就会算重复了
所以再对这种情况取一个
就可以了
记得答案-2,因为有两个点(1个)算重复了,有四个点(3个)没有算(括号里是第二种情况)
# include <cstdio>
# include <algorithm>
# include <cstring>
# include <cmath>
# include <climits>
# include <iostream>
# include <string>
# include <queue>
# include <stack>
# include <vector>
# include <set>
# include <map>
# include <cstdlib>
# include <ctime>
using namespace std;
# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)
typedef long long ll;
const int N=55;
const int mod=1e9+7;
const double eps=1e-7;
template <typename T> void read(T &x){
x=0;int f=1;
char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
x*=f;
}
//# pragma GCC optimize(2)
int n,m,cnt;
char s[N][N];
int a[N][N];
int dis[N][N][4];
int col[N][N];
int d[4][4];
int ans;
bool vis[N][N];
int mvx[4]={0,1,0,-1},mvy[4]={1,0,-1,0};
struct node{
int x,y,len;
};
void dfs(int x,int y,int color){
col[x][y]=color;
Rep(i,0,3){
int x_new=x+mvx[i],y_new=y+mvy[i];
if(x_new<1||x_new>n||y_new<1||y_new>m)continue;
if(col[x_new][y_new])continue;
if(!a[x_new][y_new])continue;
dfs(x_new,y_new,color);
}
}
void bfs(int x,int y){
queue<node> q;
q.push((node){x,y,0});
memset(vis,0,sizeof(vis));
vis[x][y]=true;
while(!q.empty()){
node u=q.front();q.pop();
if(col[u.x][u.y])dis[x][y][col[u.x][u.y]]=min(dis[x][y][col[u.x][u.y]],u.len);
Rep(i,0,3){
int x_new=u.x+mvx[i],y_new=u.y+mvy[i];
if(x_new<1||x_new>n||y_new<1||y_new>m)continue;
if(vis[x_new][y_new])continue;
vis[x_new][y_new]=true;
q.push((node){x_new,y_new,u.len+1});
}
}
}
int main()
{
memset(d,0x3f,sizeof(d));
memset(dis,0x3f,sizeof(dis));
read(n),read(m);
Rep(i,1,n)scanf("%s",s[i]+1);
Rep(i,1,n)
Rep(j,1,m)
if(s[i][j]=='X')
a[i][j]=1;
Rep(i,1,n)
Rep(j,1,m)
if(a[i][j]&&!col[i][j])
dfs(i,j,++cnt);
Rep(i,1,n)
Rep(j,1,m)
bfs(i,j);
Rep(i,1,n)
Rep(j,1,m)
Rep(k,1,3)
Rep(l,1,3)
if(k!=l)d[k][l]=min(d[k][l],dis[i][j][k]+dis[i][j][l]);
ans=min(d[1][2]+d[1][3],min(d[1][2]+d[2][3],d[1][3]+d[2][3]));
Rep(i,1,n)
Rep(j,1,m)
ans=min(ans,dis[i][j][1]+dis[i][j][2]+dis[i][j][3]);
ans-=2;
printf("%d\n",ans);
return 0;
}