Find a Way


这道题,是一个典型最短路径问题,用宽搜,但不要理解为双起点,而要理解为双宽搜。这道题有多个终点,我们不要一个一个点地枚举,这样做会超时(我试过的,而且还卡了很久不知道为什么错.而是算没个人到每个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哦!
} 
}


posted @ 2017-07-28 08:57  c201904  阅读(103)  评论(0编辑  收藏  举报