题目描述
在 nnn × mmm 的平面星球里( 5<=n5 <= n5<=n, m<=1000m <= 1000m<=1000 ),存在着 aaa 支军队 ( 2<=a<=502 <= a <= 502<=a<=50 ) , 和 bbb 支驻扎在地图中的敌军 ( 0<=b<=n∗m−a0 <= b <= n * m - a0<=b<=n∗m−a ) ,你需要确保所有军队全部合并 .
军队坐标假设为 ( xix_ixi , yiy_iyi ) ,行军一天可以到达( xi+1x_{i + 1}xi+1 , yiy_iyi )或者 ( xi−1x_{i - 1}xi−1 , yiy_iyi ) 或者( xix_ixi , yi+1y_{i + 1}yi+1 ) 或者 ( xix_ixi , yi−1y_{i - 1}yi−1 ),在与另外一支军队相遇时自动合并到另一支军队,你的部队需要避免与敌军起冲突。
战事紧急,身为司令,你需要快速计算出最少多少天所有军队全部合并完毕,如果必须跟敌军发生冲突请输出 No ,否则输出最少的天数。
注意:
在一支军队移动时,其他军队不可移动。
军队合并是依次进行的,且起点和终点都必须是军队,起点终点不固定,每次行军,可以任意指定两个现存在地图中的不同军队作为起点终点。例如有三个军队A,B,C,A->B,A合并B,B再合并C。也可以A->B,C->B。
输入描述:
输入nnn ,mmm(5<=n5 <= n5<=n, m<=1000m <= 1000m<=1000) 输入nnn行,每行mmm列, 每列用∗*∗ 表示军队 # 表示敌军 ... 表示可移动区域。
输出描述:
如果军队之间可以全部合并,输出需要多少步 反之输出No
示例1
输入
复制5 5 .#..# ..#*. *...* #.### .....
5 5 .#..# ..#*. *...* #.### .....
输出
复制6
6
说明
示例2
输入
复制5 5 ##### #.... ***## *#..# *####
5 5 ##### #.... ***## *#..# *####
输出
复制4
4
示例3
输入
复制5 5 .#*#. #.#.# ..*.. *.#.* .....
5 5 .#*#. #.#.# ..*.. *.#.* .....
输出
复制No
No
做法
看到题目时完全是懵的,完全不知道怎么实现。看了题解说是bfs求每个点之间的距离,然后建边,然后跑一遍最小生成树。感觉还得有抽象问题的能力吧。最近也遇到挺多看上去很难的题,但看了题解后其实很多自己是学过的,而且知道后很快能写出来。
#include<bits/stdc++.h>
using namespace std;
int n,m,cnt;
char a[1010][1010];
int vis[1010][1010],id[1010][1010],head[100];
int dx[]={0,0,-1,1};
int dy[]={1,-1,0,0};
struct ty{
int x,y;
int cnt;
};
vector<ty> v;
queue<ty> q;
int sign,tot,ans;
struct ty2{
int l,next,t;
}edge[10000];
void addedge(int x,int y,int z){
edge[++tot].l=z;
edge[tot].t=y;
edge[tot].next=head[x];
head[x]=tot;
}
struct ty3{
int x,len;
bool operator < (const ty3 & a) const{
return len>a.len;
}
};
int len[100],vis1[100];
priority_queue<ty3> q1;
void prime(){
memset(len,0x3f,sizeof(len));
memset(vis,0,sizeof(vis));
vis1[id[v[1].x][v[1].y]]=1;
len[id[v[1].x][v[1].y]]=0;
for(int i=head[id[v[1].x][v[1].y]];i!=-1;i=edge[i].next){
q1.push({edge[i].t,edge[i].l});
len[edge[i].t]=edge[i].l;
}
while(!q1.empty()){
ty3 tmp=q1.top();
q1.pop();
if(vis1[tmp.x]) continue;
ans+=tmp.len;
vis1[tmp.x]=1;
for(int i=head[tmp.x];i!=-1;i=edge[i].next){
if(vis1[edge[i].t]) continue;
if(len[edge[i].t]>edge[i].l){
len[edge[i].t]=edge[i].l;
q1.push({edge[i].t,edge[i].l});
}
}
}
}
void bfs(int x){
int res=0;
q.push({v[x].x,v[x].y,0});
memset(vis,0,sizeof(vis));
while(!q.empty()){
ty tmp=q.front();
q.pop();
if(vis[tmp.x][tmp.y]) continue;
vis[tmp.x][tmp.y]=1;
if(a[tmp.x][tmp.y]=='*'&&(tmp.x!=v[x].x||tmp.y!=v[x].y)){
addedge(id[v[x].x][v[x].y],id[tmp.x][tmp.y],tmp.cnt);
res++;
}
for(int i=0;i<4;i++){
int xx=dx[i]+tmp.x;
int yy=dy[i]+tmp.y;
if(xx>n||xx<1||yy>m||yy<1) continue;
if(vis[xx][yy]) continue;
if(a[xx][yy]=='#') continue;
q.push({xx,yy,tmp.cnt+1});
}
}
if(res+1!=cnt) sign=1;
}
int main(){
memset(head,-1,sizeof(head));
v.push_back({-1,-1,0});
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
if(a[i][j]=='*') {
cnt++;
v.push_back({i,j,0});
id[i][j]=v.size()-1;
}
}
}
for(int i=1;i<v.size();i++){
bfs(i);
if(sign){
cout<<"No";
return 0;
}
}
prime();
cout<<ans;
}