这道题,是一个典型最短路径问题,用宽搜,但不要理解为双起点,而要理解为双宽搜。这道题有多个终点,我们不要一个一个点地枚举,这样做会超时(我试过的,而且还卡了很久不知道为什么错.而是算没个人到每个KFC的距离,再用两人的距离和比较,取最小的。
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
long long n,b[40001][3]={0},s=0,d[201][201]={0},d1[201][201],m,direction[4][2]={{0,1},{1,0},{-1,0},{0,-1}};
char a[201][201];
queue<int>p;
queue<int>p1;
void search(int i2,int j2){
memset(d,0x3f3f3f3f,sizeof(d));
d[i2][j2]=0;
while(p.size()){
p.pop();p1.pop();
}
p.push(i2);p1.push(j2);
while(p.size()){
int sx=p.front();p.pop();
int sy=p1.front(); p1.pop();
for(int i=0;i<4;i++){
int x1=sx+direction[i][0],x2=sy+direction[i][1];
if(x1>=1&&x1<=n&&x2>=1&&x2<=m&&d[x1][x2]>d[sx][sy]+1&&a[x1][x2]!='#'){//没超出边界且没遇到墙才行(不要重复走)
p.push(x1);p1.push(x2);
d[x1][x2]=d[sx][sy]+1;
}
}
}
}
void search1(int i2,int j2){
memset(d1,0x3f3f3f3f,sizeof(d1));
d1[i2][j2]=0;
while(p.size()){
p.pop();p1.pop();
}
p.push(i2);p1.push(j2);
while(p.size()){
int sx=p.front();p.pop();
int sy=p1.front(); p1.pop();
for(int i=0;i<4;i++){
int x1=sx+direction[i][0],x2=sy+direction[i][1];
if(x1>=1&&x1<=n&&x2>=1&&x2<=m&&d1[x1][x2]>d1[sx][sy]+1&&a[x1][x2]!='#'){
p.push(x1);p1.push(x2);
d1[x1][x2]=d1[sx][sy]+1;
}
}
}
}
int main(){
while(cin>>n>>m){
long long s=0,stx1,sty1,stx2,sty2,ans=100000000;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
if(a[i][j]=='Y'){
stx1=i;sty1=j;
}
else if(a[i][j]=='M'){
stx2=i;sty2=j;
}
else if(a[i][j]=='@'){
b[++s][1]=i;b[s][2]=j;//存终点
}
}
}
search(stx1,sty1);search1(stx2,sty2);
for(int i=1;i<=s;i++){
long long time=d[b[i][1]][b[i][2]]+d1[b[i][1]][b[i][2]];//距离和
ans=min(time,ans);
}
cout<<ans*11<<endl;//记得乘以一个11哦!
}
}