誰沒事手擼魔法方向陣列啊
正解:
題目上說最少使用幾次魔法,因此一定是正常上下左右移動的優先順序更高。
bfs 的特點就是會先算隊首,這也就意味著隊首的優先順序更高。
從隊首入隊,需要使用 deque
。此題中的 step
陣列用於記錄到當前點用了多少次魔法。
#include <bits/stdc++.h>
using namespace std;
struct p{
int x, y;
};
int h, w, a, b, x, y, step[1005][1005];
//正常上下左右移動
int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
//魔法方向陣列
int sy[] = {-2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2};
int sx[] = {-2, -2, -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2};
void bfs(){
deque<p> q;//雙端佇列
q.push_back({a, b});//初始起點入隊
step[a][b] = 0;//初始時最少使用0次魔法
while(!q.empty()){
int mx = q.front().x, my = q.front().y;
q.pop_front();
for(int i = 0; i <= 3; i++){//上下左右移動的
int nx = mx + dx[i], ny = my + dy[i];
//越界
if(nx > h || ny > w || nx < 1 || ny < 1)continue;
//一個點可以重複走過,但如果新的次數還大於原來的就不用往下找了,一定不會是最優解
if(m[nx][ny] == '#' || step[nx][ny] <= step[mx][my])continue;
step[nx][ny] = step[mx][my];
q.push_front({nx, ny});//正常的優先順序高,放前面
}
for(int i = 0; i <= 23; i++){//使用魔法的
int nx = mx + sx[i], ny = my + sy[i];
if(nx > h || ny > w || nx < 1 || ny < 1)continue;
if(m[nx][ny] == '#' || step[nx][ny] <= step[mx][my] + 1)continue;
step[nx][ny] = step[mx][my] + 1;
q.push_back({nx, ny});//使用魔法的的優先順序低,放後面
}
}
if(step[x][y] != 0x3f3f3f3f) cout << step[x][y];//能走到
else cout << -1;
}
int main(){
memset(step, 0x3f, sizeof(step));//初始化,以免在取最小值時全為0
cin >> h >> w >> a >> b >> x >> y;
for(int i = 1; i <= h; i++)
for(int j = 1; j <= w; j++)
cin >> m[i][j];
bfs();
return 0;
}