bfs解決poj 2312 battle city(優先隊列)

Battle City

題目鏈接

題目描述

簡單描述一下,細節點擊題目鏈接進行查看。

給定m,n,然後給定m*n的矩陣,矩陣元素由 ‘Y’ (you), ‘T’ (target), ‘S’ (steel wall), ‘B’ (brick wall), ‘R’ (river) and ‘E’ (empty space)中的幾個元素組成,並且’Y’和’T’只出現一次,現要求從Y儘快走到T。

其中B表示的位置必須要射擊一次,再走一步纔算到達,E表示的位置可走一步直接到達,S和R表示的位置不可通過。

解題思路

要求從某點到某點的最短路徑想到用bfs,廣度優先搜索,最先到達目標地點的路徑爲最短,但是這個題目與普通的bfs模板略有不同,在這個題目中 每個節點的權值是可能不同的,對於字符爲B的位置,它首先需要通過射擊打碎障礙,然後再走一步通過。所以就要用到優先隊列。

bfs的思路很簡單,就是在每一個位置分別向上下左右走一步,然後看這個點是否滿足條件(包括是否在地圖內,是否已經走過,還有這個點是否可以走),如果滿足條件我們就可以走一步,然後將一個節點更新並壓入隊列。

代碼如下

#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;

int m,n;
char s[305][305];
bool vis[305][305];
int sx,sy;//Y即開始所在的座標
int ex,ey;//T即結束的座標
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};//四個方向
int ans;

struct node {
	int x,y,step;
	friend bool operator < (node a,node b) { //節點步數少的優先級高。
		return a.step > b.step;
	}
};
void bfs() {
	priority_queue<node>q;
	node start;
	start.x = sx;
	start.y = sy;
	start.step = 0;
	vis[sx][sy] = true;
	q.push(start);
	while(!q.empty()) {
		node top = q.top();
		q.pop();
		//printf("top.x = %d,top.y = %d\n",top.x,top.y);
		if(top.x == ex && top.y == ey) {//結束條件 如果不能到達,則ans仍爲-1
			ans = top.step;
			return;
		}
		for(int i = 0; i < 4; i++) {
			int x = top.x + dir[i][0];
			int y = top.y + dir[i][1];
			if(x>=0 && x<m && y>=0 && y<n && !vis[x][y] && s[x][y]!='R' && s[x][y]!='S'){			
				node now = top;
				if(s[x][y] == 'B') now.step+=2;
				else now.step++;
				now.x = x;
				now.y = y;
				vis[x][y] = true;
				q.push(now);
			}
		}
	}
	return;
}
int main() {
	while(scanf("%d%d",&m,&n)) {
		if(m==0 && n==0) break;
		for(int i = 0; i< m; i++) {
			scanf("%s",s[i]);
			for(int j = 0; j< n; j++) {
				if(s[i][j] == 'Y') {
					sx = i;
					sy = j;
				}
				if(s[i][j] == 'T') {
					ex = i;
					ey = j;
				}
			}
		}
		ans = -1;
		memset(vis,false,sizeof(vis));
		//printf("ex = %d,ey = %d\n",ex,ey);
		bfs();
		printf("%d\n",ans);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章