本题才是用BFS进行求解,但是单纯的使用BFS会出现错误,因为并不是每一步都是相同的消耗,如果让消耗多的先进入了那么该点就不是最小的消耗。可以使用一个优先队列来维护,每次都让最小的消耗去走,这样可以保持没一点都是由最小的来进入。
但在本题当中,由于是01之间的消耗。所以可以使用一个双端队列,如果是0的消耗就放入对头,如果是1的消耗就放到队尾这样就保持队首一直是小的。
在这里面到达某一个坐标的消耗用一个二维数组保存,并且要在队列头拿出来的时候进行判断不然会出现错误。
但在本题当中,由于是01之间的消耗。所以可以使用一个双端队列,如果是0的消耗就放入对头,如果是1的消耗就放到队尾这样就保持队首一直是小的。
在这里面到达某一个坐标的消耗用一个二维数组保存,并且要在队列头拿出来的时候进行判断不然会出现错误。
#include <bits/stdc++.h> using namespace std; const int maxn = 1000+1; struct Node { int x, y; }; int a[maxn][maxn]; int n, m; int begin_x, begin_y; int end_x, end_y; int ans = 0; // map<pair<int, int>, int> fd; int vis[maxn][maxn]; deque<Node> pq; int mv[8][2] { {-1,0},//北 {-1,1},//东北 {0,1},//东 {1,1},//东南 {1,0},//南 {1,-1},//西南 {0,-1},//西 {-1,-1}//西北 }; void BFS() { vis[begin_x][begin_y] = 0; pq.push_front({begin_x, begin_y}); while (pq.size()) { Node p = pq.front(); int x=p.x;int y=p.y; pq.pop_front(); if (x==end_x&&y==end_y) { return ; } //进行移动,移动过程中判断是否消耗体力 for (int i=0;i<8;i++) { int next_x = x+mv[i][0]; int next_y = y+mv[i][1]; if (next_x<=0||next_x>n||next_y<=0||next_y>m) continue; if (a[x][y]==i){ if (vis[next_x][next_y]<=vis[x][y]) continue; } else if (vis[next_x][next_y]<=vis[x][y]+1) continue; if (a[x][y]==i) { pq.push_front({next_x, next_y}); vis[next_x][next_y] = vis[x][y]; // fd[{next_x, next_y}] = val; }else { pq.push_back({next_x, next_y}); vis[next_x][next_y] = vis[x][y]+1; // fd[{next_x, next_y}] = val+1; } } } } int main() { cin>>n>>m; for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { scanf("%1d", &a[i][j]); } } int T; cin>>T; while (T--) { memset(vis, 0x3f, sizeof(vis)); ans = 0; while (!pq.empty()) pq.pop_back(); cin>>begin_x>>begin_y; cin>>end_x>>end_y; BFS(); cout<<vis[end_x][end_y]<<endl; } return 0; }