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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值