01BFS
01BFS
如果图的边权全部都为1,那么用普通的BFS就可以解决。但如果边权不等,就需要一个优先队列,时间复杂度带了一个log。对于边权为
01BFS利用一个双端队列(deque)来维护搜索扩展出来的结点。当边权为0时,使用push_front把新结点压入队列头部。当边权为1时,使用push_back把新结点压入队列尾部。这样可以保证队列里面元素的单调性,保证最先出队的节点代价一定小于等于后出队的节点代价,保证某个点第一次遍历时的答案一定是最佳的答案。
对于算法正确性,由于01BFS队列内的所有节点当前答案一定只有两个,分为前面一部分和后面一部分,每次取出都是从队首取出,队首元素和遍历到的元素之间的代价如果为1,则当前代价加1后一定是最大的(或并列最大),而如果代价为0,则答案不变,因为取出的是队首的(最小的)所以遍历到的还是最小的,满足条件。
Ocean Currents
题意: 在一个
分析:往一个方向走,要么代价为1,要么代价为0,所以这是一个01BFS。需要注意的是,不一定先遍历到的点的权值最小,但可以保证先出队的是最小的,所以我们不能用一个bool的vis来判断走过没,而要用一个int的dis存距离,通过dis的大小来判断是否入队
bool check(int x,int y){
return x<=n&&x>=1&&y<=m&&y>=1;
}
void bfs(int bx,int by,int ex,int ey){
memset(dist,-1,sizeof(dist));
deque<node>q;
q.push_front({bx,by,0});
while(!q.empty()){
int x=q.front().x;
int y=q.front().y;
int val=q.front().val;
q.pop_front();
if(dist[x][y]!=-1){
continue;
}
dist[x][y]=val;
if(x==ex&&y==ey){
printf("%d")
printf("%d\n",dist[x][y]);
return ;
}
for(int i=0;i<8;i++){
int nx=x+dirx[i];
int ny=y+diry[i];
if(check(nx,ny)==0){
continue;
}
if(int(a[x][y]-'0')==i){
q.push_front({nx,ny,val});
} else{
q.push_back({nx,ny,val+1});
}
}
}
return;
}
Labyrinth
题意: 一个
分析: 假设迷宫起始起点为
void bfs(int bx,int by){
memset(dist,0x3f3f3f3f,sizeof(dist));
deque<node>q;
q.push_front({bx,by});
dist[bx][by]=0;
while(!q.empty()){
int x=q.front().x;
int y=q.front().y;
q.pop_front();
for(int i=0;i<4;i++){
int nx=x+dirx[i];
int ny=y+diry[i];
if(check(nx,ny)==0){
continue;
}
int w=(diry[i]!=0);
if(dist[nx][ny]>dist[x][y]+w){
dist[nx][ny]=dist[x][y]+w;
if(!w){
q.push_front({nx,ny});
} else{
q.push_back({nx,ny});
}
}
}
}
return;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(dist[i][j]==0x3f3f3f3f){
continue;
}
int a=j-by;//r-l=a; r+l=dist
int l=(dist[i][j]-a)/2;
int r=(a+dist[i][j])/2;
if(l<=L&&r<=R){
ans++;
}
}
}