1. 程式人生 > >ZOJ 1649 BFS/最短路

ZOJ 1649 BFS/最短路

給你起點和終點,然後讓你在二維迷宮裡面去找一個人,和一般的BFS的唯一差別就是這裡面設定了一些守衛,你要殺掉這個守衛就必須要多花費一秒的時間,讓你求出最終到達的最短的步數。 對於一般的BFS我們知道,它不但可以去找路徑,而且還能保證它最終的結果是最短路。因為它記錄了步數,它知道每一步最大能拓展的位置。那麼在這道題裡面,我們直接去求卻是不行的,我們最先找到的那一條路徑卻未必是最短的,那麼我們就要按照步數的順序來拓展這個BFS,我們可以考慮用優先佇列給步數排序,這樣保證步數少的在前面,這樣最後找到就是答案。 當然我們也可以把這個問題轉化成最短路,對於沒有守衛的普通格子,相當於邊權為1,對於有守衛的格子邊權為2,然後我們直接跑spfa就可以了,不過一段時間不寫居然也搞出了一堆傻逼操作,比如什麼起始位置的距離沒有置為0,胡亂鬆弛。總而言之還是基礎不紮實。 另外還有一個優先佇列(其實不單單是優先佇列)過載運算子都是去過載小於號,它們實際上都是用小於來確定順序的。 SPFA:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
char mp[200+15][200+15];
int vis[200+15][200+15]; 
int stx,sty,edx,edy;
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
int dis[200+15][200+15];
int n,m;
struct node{
	int x,y;
	node(){}
	node(int x,int y):x(x),y(y) {}
};
void spfa() {
	queue<node> q;
	vis[stx][sty]=1;
	dis[stx][sty]=0;
	q.push(node(stx,sty));
	while(!q.empty()) {
		node u=q.front();q.pop();
		int x=u.x,y=u.y;
		vis[x][y]=0;
		for(int i=0;i<4;i++) {
			int nx=x+dx[i],ny=y+dy[i];
			if(nx<1||nx>n||ny<1||ny>m||mp[nx][ny]=='#') continue;
			if(mp[nx][ny]=='.'||mp[nx][ny]=='r') {
				if(dis[nx][ny]>dis[x][y]+1) {
					dis[nx][ny]=dis[x][y]+1;
					if(!vis[nx][ny]) {
						q.push(node(nx,ny));
						vis[nx][ny]=1;
					}	
				}
			}
			if(mp[nx][ny]=='x') {
				if(dis[nx][ny]>dis[x][y]+2) {
					dis[nx][ny]=dis[x][y]+2;
					if(!vis[nx][ny]) {
						q.push(node(nx,ny));
						vis[nx][ny]=1;
					}
				}
				
			}
		}
	}
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	while(cin>>n>>m) {
		memset(dis,inf,sizeof(dis));
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++) {
				cin>>mp[i][j];
				if(mp[i][j]=='a') stx=i,sty=j;
				if(mp[i][j]=='r') edx=i,edy=j; 
		}
		spfa();
		if(dis[edx][edy]!=inf) printf("%d\n",dis[edx][edy]);
		else printf("Poor ANGEL has to stay in the prison all his life.\n");
	}
	return 0;
}


優先佇列BFS

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=200+15;
char mp[maxn][maxn];
bool vis[maxn][maxn];
int n,m,stx,sty,edx,edy;
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
struct node {
	int x,y,step;
	node() {}
	node(int x,int y,int step):x(x),y(y),step(step){}
};
bool operator<(const node& a,const node& b){
		if(a.step>b.step) return true;
		else return false; 
	}
int bfs() {
	priority_queue<node> q;
	vis[stx][sty]=true;
	q.push(node(stx,sty,0));
	while(!q.empty()) {
		node u=q.top();q.pop();
		int x=u.x,y=u.y,step=u.step;
		if(x==edx&&y==edy) return step;
		for(int i=0;i<4;i++) {
			int nx=x+dx[i];
			int ny=y+dy[i];
			if(nx<1||nx>n||ny<1||ny>m||vis[nx][ny]||mp[nx][ny]=='#') continue;
			if(mp[nx][ny]=='.'||mp[nx][ny]=='r')  {
				vis[nx][ny]=true;
				q.push(node(nx,ny,step+1));
			} 
			if(mp[nx][ny]=='x') {
				vis[nx][ny]=true;
				q.push(node(nx,ny,step+2));
			}
		}
	}
	return -1;
}
void clear() {
	memset(vis,0,sizeof(vis));
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	while(cin>>n>>m) {
		clear();
		for(int i=1;i<=n;i++)
		 	for(int j=1;j<=m;j++) {
		 		cin>>mp[i][j];
		 		if(mp[i][j]=='a') stx=i,sty=j;
		 		if(mp[i][j]=='r') edx=i,edy=j;
			}
		int ans=bfs();
		if(ans!=-1) cout<<ans<<endl;
		else cout<<"Poor ANGEL has to stay in the prison all his life."<<endl; 
	}
	return 0;
}