AT168 自宅からの脱出

看到其它题解都是数组模拟BFS,没人用STL的

那我就来写一写STL吧

题目传送门

sol

题目意思都很清晰吧,分为两个部分:

①从我的房间到电脑

②从电脑到我家的门

求最短距离,很明显用两遍BFS即可,“#”表示障碍(即不能走),“S”表示我的房间,“C”电脑位置,“G”表示我家的门。首先就把S,C,G的位置循环搜出来

然后呢,跑两遍BFS,第一次起点为S,终点为C,第二次起点为C,终点为G。注意:在第二次开始搜的时候数组一定要清空

code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
typedef long long ll;
using namespace std;
inline int max(int a,int b){return a>b?a:b;}
inline int min(int a,int b){return a<b?a:b;}
inline int rd(){
	int res=0,sign=1;char ch;
	while((ch=getchar())<'0'||ch>'9')if(ch=='-')sign=-1;res=res*10+ch-48;
	while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;
	return res*sign;
}
const int maxn=510;
int n,m;//边长 
int dx[5]={0,0,1,-1};
int dy[5]={1,-1,0,0};//方向数组,表示下一步的四个方向 
char mapp[maxn][maxn];//存储我家 
int ans[maxn][maxn];//记录步数 
bool flag[maxn][maxn];//标记是否走过 
int sx,sy,cpx,cpy,ex,ey;//sx、sy表示S(我的房间),cpx、cpy表示C(电脑),ex、ey表示G(我家的门) 
queue<int>q1,q2;//定义队列 
queue<int>qq1,qq2;//因为STL队列不能清空(只有双端队列才能清空),所以定义两个 
void init(){//读入 
	n=rd(),m=rd();
	for(int i=1;i<=n;i++) 
	 for(int j=1;j<=m;j++){
	 	cin>>mapp[i][j];
	 	if(mapp[i][j]=='S') sx=i,sy=j;
	 	if(mapp[i][j]=='C') cpx=i,cpy=j;
	 	if(mapp[i][j]=='G') ex=i,ey=j;//把S、C、G坐标搜出来 
 	} 
} 
int sum=0;
bool used=false,t=false;
void BFS1(){//第一遍BFS,从S到C 
	memset(flag,0,sizeof(flag));
	memset(ans,0,sizeof(ans));
	used=false;
	q1.push(sx),q2.push(sy);
	flag[sx][sy]=1;
	while(!q1.empty()){
		int x=q1.front(),y=q2.front();
		q1.pop(),q2.pop();
		if(x==cpx&&y==cpy){
			sum+=ans[x][y];
			used=1;//如果能到达目的地,标记起来 
		}
		for(int i=0;i<4;i++){
			int xx1=x+dx[i];
			int yy1=y+dy[i];
			if(xx1>=1&&xx1<=n&&yy1>=1&&yy1<=m&&mapp[xx1][yy1]!='#'&&!flag[xx1][yy1]){
				flag[xx1][yy1]=1;
				ans[xx1][yy1]=ans[x][y]+1;
				q1.push(xx1),q2.push(yy1);
			}
		}
		if(used)break;
	}
	if(!used)//如果不能到 ,输出-1 
	 puts("-1"),t=1;
}
void BFS2(){//第二遍BFS,从C到G 
	memset(flag,0,sizeof(flag));
	memset(ans,0,sizeof(ans));
	used=false;
	qq1.push(cpx),qq2.push(cpy);
	flag[cpx][cpy]=1;
	while(!qq1.empty()){
		int x=qq1.front(),y=qq2.front();
		qq1.pop(),qq2.pop();
		if(x==ex&&y==ey){
			sum+=ans[x][y];
			used=1;//同上 
		}
		for(int i=0;i<4;i++){
			int xx1=x+dx[i];
			int yy1=y+dy[i];
			if(xx1>=1&&xx1<=n&&yy1>=1&&yy1<=m&&mapp[xx1][yy1]!='#'&&!flag[xx1][yy1]){
				flag[xx1][yy1]=1;
				ans[xx1][yy1]=ans[x][y]+1;
				qq1.push(xx1),qq2.push(yy1);
			}
		}
		if(used)break;
	}
	if(!used)
	 puts("-1"),t=1;//同上 
}
int main(){
	init();
	BFS1();
	if(t)return 0;//如果不能到就退出程序 
	t=false;
	BFS2();
	if(t)return 0;//同上 
	cout<<sum<<endl;//完美输出 
	return 0;
}

总得来说,题目还是比较简单的,就是板子题,细节很多,很容易写错

posted @ 2020-05-22 22:50  qzwer  阅读(244)  评论(0编辑  收藏  举报