1. 程式人生 > >NBUT OJ 1642 簡單的圖論問題? 最短路問題,BFS

NBUT OJ 1642 簡單的圖論問題? 最短路問題,BFS

                相信第一個最短路問題應該幾乎都是沒什麼問題的。。直接跑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;
}