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