NBUT OJ 1642 簡單的圖論問題? 最短路問題,BFS
阿新 • • 發佈:2019-02-14
相信第一個最短路問題應該幾乎都是沒什麼問題的。。直接跑BFS就可以了,第二個。我感覺和這裡的題目有點像 POJ 1724 同樣都是在約束條件下的最短路,因此解決這些問題的方法應該也是類似的,我先闡述這個問題吧,那個問題我以後在寫一篇部落格,然後這兩個相互連結,扯遠了。連結補上:有約束的最短路
第二種路徑的要求就是不能沿著同樣的方向再走一次,我們知道普通的最短路上是沒有環的,也就是每個格子只到達一次,那麼,我們可以類比過來,在這種約束條件下,到達一個格子上的此時的方向也只能有一次,意思就是你第一次到達A格的時候方向是向下,你走了許多步之後,假若你還到了A格,那麼此時你的方向一定不會是向下,否則你走的這條路一定不是最短路。然後用一個500×500×5的陣列來標記上下左右的狀態就好,然後實現的時候注意一下,不要把牆壁的點也加進去了。,,我的實現方法是把牆壁的權值理解為無窮大。。在第一次寫的時候依然把牆壁加進去了。。。其實多做了及其多的無窮的搜尋,這個還是吃了苦頭的。
Tips:利用一個優先佇列來儲存狀態,距離越短的權值越高,所以在這種情況下,一旦取出的第一個點是終點,那麼便可以退出迴圈,因為此時一定是最短路徑。另外一定就是在push的時候需要滿足約束條件。
(程式碼可能會有點長呀,,下次嘗試用陣列來代替方向,然後寫一個判斷函式好了。)
#include<cstdio> #include<queue> #include<cstring> using namespace std; char str[5]; int n,m,r1,c1,r2,c2,board[505][505],len1[505][505],times=1,ans=0x3f3f3f3f; bool flag[505][505],vis[505][505][5]; struct Node{ int x,y,dir,dis; Node(int a=0,int b=0,int c=0,int d=0){x=a,y=b,dir=c,dis=d;} bool operator<(const Node& a)const{return dis>a.dis;}; }te; queue<Node> q; priority_queue<Node> qw; int main(){ while(scanf("%d%d%d%d%d%d",&n,&m,&r1,&c1,&r2,&c2)!=EOF){ for(int i=0;i<n;++i) for(int j=0;j<m;++j){ scanf("%s",str); if(str[0]=='*') board[i][j]=0x3f3f3f3f; else sscanf(str,"%d",&board[i][j]); } for(int i=0;i<n;++i) memset(len1[i],0x3f,sizeof(int)*m); len1[r1-1][c1-1]=board[r1-1][c1-1]; q.push(Node(r1-1,c1-1)); while(!q.empty()){ te=q.front();q.pop(); flag[te.x][te.y]=false; if(te.x+1==r2&&te.y+1==c2) continue; if(te.y-1>=0&&len1[te.x][te.y-1]>len1[te.x][te.y]+board[te.x][te.y-1]){ len1[te.x][te.y-1]=len1[te.x][te.y]+board[te.x][te.y-1]; if(!flag[te.x][te.y-1]) flag[te.x][te.y-1]=true,q.push(Node(te.x,te.y-1)); } if(te.y+1<m&&len1[te.x][te.y+1]>len1[te.x][te.y]+board[te.x][te.y+1]){ len1[te.x][te.y+1]=len1[te.x][te.y]+board[te.x][te.y+1]; if(!flag[te.x][te.y+1]) flag[te.x][te.y+1]=true,q.push(Node(te.x,te.y+1)); } if(te.x-1>=0&&len1[te.x-1][te.y]>len1[te.x][te.y]+board[te.x-1][te.y]){ len1[te.x-1][te.y]=len1[te.x][te.y]+board[te.x-1][te.y]; if(!flag[te.x-1][te.y]) flag[te.x-1][te.y]=true,q.push(Node(te.x-1,te.y)); } if(te.x+1<n&&len1[te.x+1][te.y]>len1[te.x][te.y]+board[te.x+1][te.y]){ len1[te.x+1][te.y]=len1[te.x][te.y]+board[te.x+1][te.y]; if(!flag[te.x+1][te.y]) flag[te.x+1][te.y]=true,q.push(Node(te.x+1,te.y)); } } qw.push(Node(r1-1,c1-1,0,board[r1-1][c1-1])); for(int i=1;i<=4;++i) vis[r1-1][c1-1][i]=true; while(!qw.empty()){ te=qw.top();qw.pop(); if(te.x==r2-1&&te.y==c2-1){ ans=te.dis; break; } if(te.dir!=1&&te.y-1>=0){ if(!vis[te.x][te.y-1][1]&&board[te.x][te.y-1]!=0x3f3f3f3f) qw.push(Node(te.x,te.y-1,1,te.dis+board[te.x][te.y-1])),vis[te.x][te.y-1][1]=true; } if(te.dir!=2&&te.y+1<m){ if(!vis[te.x][te.y+1][2]&&board[te.x][te.y+1]!=0x3f3f3f3f) qw.push(Node(te.x,te.y+1,2,te.dis+board[te.x][te.y+1])),vis[te.x][te.y+1][2]=true; } if(te.dir!=3&&te.x-1>=0){ if(!vis[te.x-1][te.y][3]&&board[te.x-1][te.y]!=0x3f3f3f3f) qw.push(Node(te.x-1,te.y,3,te.dis+board[te.x-1][te.y])),vis[te.x-1][te.y][3]=true; } if(te.dir!=4&&te.x+1<n){ if(!vis[te.x+1][te.y][4]&&board[te.x+1][te.y]!=0x3f3f3f3f) qw.push(Node(te.x+1,te.y,4,te.dis+board[te.x+1][te.y])),vis[te.x+1][te.y][4]=true; } } while(!qw.empty())qw.pop(); printf("Case %d: %d %d\n",times++,(len1[r2-1][c2-1]==0x3f3f3f3f)?-1:len1[r2-1][c2-1],(ans>=0x3f3f3f3f)?-1:ans);ans=0x3f3f3f3f; for(int i=0;i<n;++i) for(int j=0;j<m;++j) memset(vis[i][j],0,sizeof(bool)*5); } return 0; }