POJ 1915-Knight Moves (單向BFS && 雙向BFS 比較)
阿新 • • 發佈:2019-02-13
題意:8個方向的 馬跳式走法 ,已知起點 和終點,求最短路
研究了一下雙向BFS,不是很難,和普通的BFS一樣,雙向BFS不過是從 起點和終點同時開始搜尋,可減少搜尋時間
當兩條搜尋路線相遇時,結束。
貌似有一年百度的招聘 筆試,就是雙向BFS。。。。
下面,比較一下BFS 和 雙向BFS的用時;
BFS
STL的queue可能會浪費一點時間
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <queue> const int N = 310; using namespace std; int mapp[N][N]; bool vis[N][N]; struct node{ int x,y,ans; }; int n; int mv[8][2] = {{1,2},{1,-2},{2,1},{2,-1},{-2,1},{-2,-1},{-1,2},{-1,-2}}; void BFS(int sx,int sy,int ex,int ey) { queue<node>q; node t,f; memset(vis,0,sizeof(vis)); f.x = sx; f.y = sy; f.ans = 0; vis[sx][sy] = true; q.push(f); while(!q.empty()) { t = q.front(); q.pop(); if(t.x==ex && t.y==ey) { printf("%d\n",t.ans); return ; } for(int i = 0;i<8;i++) { f.x = t.x + mv[i][0]; f.y = t.y + mv[i][1]; if(!vis[f.x][f.y]&& 0<=f.x && f.x <n && 0<=f.y && f.y<n) { f.ans = t.ans + 1; q.push(f); vis[f.x][f.y] = true; } } } } int main() { int t,sx,sy,ex,ey; std::ios::sync_with_stdio(false); scanf("%d",&t); while(t--) { scanf("%d",&n); scanf("%d%d",&sx,&sy); scanf("%d%d",&ex,&ey); BFS(sx,sy,ex,ey); } return 0; }
雙向BFS
時間差的不是很大,但是理論上,時間複雜度會減少若干倍,如果資料大的話,時間差會很明顯
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <queue> const int N = 310; using namespace std; int mapp[N][N]; int vis[N][N]; struct node{ int x,y; }; int n; int mv[8][2] = {{1,2},{1,-2},{2,1},{2,-1},{-2,1},{-2,-1},{-1,2},{-1,-2}}; int dis[N][N]; void BFS(int sx,int sy,int ex,int ey) { if(sx==ex && sy == ey) { printf("0\n"); return ; } queue<node>q; node t,f; memset(vis,0,sizeof(vis)); memset(dis,0,sizeof(dis)); f.x = sx; f.y = sy; t.x = ex; t.y = ey; vis[sx][sy] = 1; //從起點開始搜尋的路線 標記為1 vis[ex][ey] = 2; //從終點開始搜尋的路線 標記為2 q.push(f); q.push(t); while(!q.empty()) { t = q.front(); q.pop(); for(int i = 0;i<8;i++) { f.x = t.x + mv[i][0]; f.y = t.y + mv[i][1]; if(0<=f.x && f.x <n && 0<=f.y && f.y<n) { if(!vis[f.x][f.y]) { dis[f.x][f.y] = dis[t.x][t.y] + 1; q.push(f); vis[f.x][f.y] = vis[t.x][t.y]; } else if(vis[f.x][f.y]!=vis[t.x][t.y]) //兩者相遇 { printf("%d\n",dis[f.x][f.y]+dis[t.x][t.y] + 1); //會漏掉相遇的那個點,所以要加1 return ; } } } } } int main() { int t,sx,sy,ex,ey; std::ios::sync_with_stdio(false); scanf("%d",&t); while(t--) { scanf("%d",&n); scanf("%d%d",&sx,&sy); scanf("%d%d",&ex,&ey); BFS(sx,sy,ex,ey); } return 0; }