01bfs,也就是说,对于遍历到的每一个点,有两种选择,0和1,可以是消耗的能量为0和消耗的能量不为0(1、2、3。。。都可以,只要存在),那么当我们遍历图来寻找最短路时,应该选择将消耗能量为0的方向放在队首,然后让有能量消耗的方向放在队尾(用双向队列),保证先遍历不消耗能量的方向,因为其与该点的距离相当于为0,这样就保证了队列取出顺序始终为距起点距离的升序。
Ocean Currents:
对于在一大片水域上航行的船只来说,强烈的水流可能是危险的,但如果经过仔细的规划,它们会变得危险
可以被用来帮助船到达目的地。你的工作就是帮助制定计划。
在每个位置,电流都流向某个方向。机长可以选择要么跟着船走
电流的流动,不使用能量,或以一个正方形为代价向任何其他方向移动
能源单位。船总是朝以下八个方向之一移动:北、南、东、西,
东北、西北、东南、西南。船不能离开湖边。
你要帮助他制定一个策略,以最低的能耗到达目的地。
湖泊被表示为矩形网格。输入的第一行包含两个整数r和c
网格中的行数和列数。网格的行数不超过1000行,也不超过1000行
柱。以下r行中的每一行都包含c字符,每个字符都是0到7(含0到7)之间的数字。
字符“0”表示电流向北流动(即在网格中向上流动,方向为下降
行数),“1”表示流向东北,“2”表示流向东(即向列增加的方向)
数字),“3”表示东南方向,顺时针方向依次类推:
7 0 1
\|/
6-*-2
/|\
5 4 3
几个细节:
一是要用双向队列
二:
对于每个点,它应该是要可以走过多次的,来保证其到起点的最短距离能够更新,所以01bfs不需要vis数组。
A
B C
这里有AB C三个点,假设B、C的距离都是5,B到A的能量是1,C到A的能量为0,如果不巧是先从B开始走那么A的距离就会是6,如果我们又不巧建了个vis,把A点标记掉了,那么A的距离就定死了,但其实C到A的距离只有5,A的距离应该是要更新的。所以在01bfs里面,我们不需要vis。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int r,c,n;
int dis[1010][1010];
int vis[1010][1010];
char mass[1010][1010];
int mas[1010][1010];
int dir[8][2] = {{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
bool inmap(int x,int y){
return x&&y&&x<=r&&y<=c;
}
void bfs(int x1,int y1,int x2,int y2){
memset(dis,0x3f3f,sizeof(dis));
memset(vis,0,sizeof vis);
deque<pair<int,int>> q;
while(q.size()) q.pop_front();
q.push_front(make_pair(x1,y1));
dis[x1][y1]=0;
vis[x1][y1]=1;
while(!q.empty()){
int x=q.front().first;
int y=q.front().second;
q.pop_front();
//if(x==x2&&y==y2){cout<<dis[x][y]<<endl;return;}
// =================================================
for(int i=0;i<8;++i){
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(inmap(xx,yy)&&!vis[xx][yy]) {
int add = (i != mas[x][y]);
if(dis[xx][yy]>dis[x][y]+add){
dis[xx][yy] = dis[x][y] +add;
//vis[xx][yy]=1;
if(add) q.push_back(make_pair(xx,yy));
else q.push_front(make_pair(xx,yy));
}
// ========================================================
// if(i=='mas[x][y]'){
// q.push_front(make_pair(xx,yy));
// dis[xx][yy]=dis[x][y];
// }
// else{
// q.push_back(make_pair(xx,yy));
// dis[xx][yy]=dis[x][y]+1;
// }
}
}
}
cout<<dis[x2][y2]<<endl;
//cout<<(dis[x2][y2]?dis[x2][y2]-1:0)<<endl;
return;
}
int main()
{
cin>>r>>c;
for(int i=1;i<=r;++i){
cin>>mass[i]+1;
}
for(int i=1;i<=r;++i){
for(int j=1;j<=c;++j){
mas[i][j]=mass[i][j]-'0';
}
}
cin>>n;
for(int i=1;i<=n;++i){
int a,b,c,d;
cin>>a>>b>>c>>d;
bfs(a,b,c,d);
}
return 0;
}