UVA439-最短路-BFS
阿新 • • 發佈:2018-12-19
前一段時間學BFS(寬度優先搜尋)最短路的時候,紫書上那個題感覺太複雜了,debug了幾天。。。還好最後AC了。
今天發現一個簡單的題,而且還覺得挺有意思的,用這個題來學BFS最短路我覺得更合適。這道題題意簡單,輸入輸出也簡單,所以程式碼較短。
分析:
第一次看到用bfs求最短路的程式碼感覺很神奇,竟然還可以這樣做。在沒有學bfs之前,我都是用dfs遍歷所有路找出最短的(超時難免了)。bfs可以用佇列實現,要做的就是把當前所在節點的所有下一個節點入列,這樣就保證了從佇列讀取出來的節點都是第n步或者n+1步了,直到發現終點為止,這條路就是最短路。
實現這個思路有幾個巧妙的地方,就是該怎麼找第n+1個節點。在這道題中,下一個節點可能有8個,用迴圈可以構造出這8個節點出來(詳情見程式碼)。當然8個節點並不是都可以,超出棋盤的去掉,已經入過列的節點去掉。
還有個問題就是怎麼算走了多少步。我把這個資料存在一個8*8陣列中,每個節點一定有唯一的步數,並且還順便把這個陣列用來判斷一個節點是否走過。
實現程式碼:
其中的vis陣列很關鍵,構造下一個節點程式碼部分較巧妙。
#include<cstdio> #include<queue> #include<cstring> #include<cstdlib> struct Point { Point(int r,int c):r(r),c(c) {} int r,c; }; char s1[3],s2[3]; int vis[8][8],begin_r,begin_c,end_r,end_c; int bfs() { memset(vis,0,sizeof(vis)); vis[begin_r][begin_c]=1; std::queue<Point> q; Point p(begin_r,begin_c); q.push(p); while(!q.empty()) { p=q.front(); q.pop(); if(p.r==end_r&&p.c==end_c) break; for(int i=-2; i<3; ++i) for(int j=-2; j<3; ++j) if(i&&j&&abs(i)!=abs(j)&&p.r+i>-1&&p.r+i<8&& p.c+j>-1&&p.c+j<8&&!vis[p.r+i][p.c+j]) { vis[p.r+i][p.c+j]=vis[p.r][p.c]+1; q.push(Point(p.r+i,p.c+j)); } } return vis[p.r][p.c]-1; } int main() { while(scanf("%s",s1)==1) { begin_r=s1[0]-'a'; begin_c=s1[1]-'1'; scanf("%s",s2); end_r=s2[0]-'a'; end_c=s2[1]-'1'; printf("To get from %s to %s takes %d knight moves.\n",s1,s2,bfs()); } }