天天看點

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;
}

           

總得來說,題目還是比較簡單的,就是闆子題,細節很多,很容易寫錯