0-1BFS(双端队列,洛谷P4667 [BalticOI 2011] Switch the Lamp On 电路维修 (Day1)题解)
对于权重为0或1的路径搜索中,使用双端队列可以对最短路问题进行时间复杂度的优化,由于优先队列的O(longn)级别的插入时间,对于双端队列O(1)插入可以将时间复杂度减少至O(M);
https://www.luogu.com.cn/problem/P4667
#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
bool tin=0;
char ma[505][505];// 存图
int vis[505][505],se[505][505];//vis记录步数,se记录是否出过一次队列
deque <array<int,2>> dq;//双端队列记录点
int dx[]={-1,-1,1,1},dy[]={-1,1,1,-1},ex[]={-1,-1,0,0},ey[]={-1,0,0,-1};
//dx,dy为下一个点的位移量,ex,ey为对应格子的位移
string s="\\/\\/";//正确连接的状态,符合该状态即无需旋转
void solve()
{int n,m;cin>>n>>m;for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>ma[i][j];//输入图 }}for(int i=0;i<=n;i++){for(int j=0;j<=m;j++){vis[i][j]=INT_MAX;se[i][j]=0;//重置位置以及步数数组 }}dq.push_back({0,0});vis[0][0]=0;//存入起点 while(!dq.empty()){int x=dq.front()[0],y=dq.front()[1];dq.pop_front();//取头点 if(se[x][y])continue;se[x][y]=1;//来过不再进行 for(int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i],exx=x+ex[i],eyy=y+ey[i];//算出下一个点以及两点间对应的连接情况 if(xx<0||xx>n||yy<0||yy>m) continue;//越界 int d=vis[x][y]+(ma[exx][eyy]!=s[i]);//距离 if(d<vis[xx][yy])//更优距离就更新 {vis[xx][yy]=d;if(ma[exx][eyy]==s[i]){dq.push_front({xx,yy});//是正确连接放在头部 }elsedq.push_back({xx,yy});//否则放在尾部 }} }if(vis[n][m]==INT_MAX)cout<<"NO SOLUTION";elsecout<<vis[n][m];
}
signed main()
{ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);int T=1;if(tin)cin>>T;while(T--){solve();}return 0;
}