• 搜索专题:问题 E: 挑战ACM迷宫


    这里写图片描述
    这是往年校赛的一道题,最开始做这道题的时候还没有系统的学习过搜索,用了C语言学的回溯法尝试,毫无疑问的TLE;
    学习了DFS之后,自己的剪枝功力不够,又是TLE,最后学了BFS之后,哇,终于做出来了,别提多开心了,然后意识到这道题其实很简单的,剋以用BFS标记法和更改步数法(更改最小消耗),后来发现这种题也可以建图跑迪杰斯特拉做;
    BFS标记法:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    
    using namespace std;
    const int N = 100 + 5;
    int mat[N][N];
    bool visit[N][N];
    typedef struct node{
        int x,y,val;
        bool operator < (const node x)const {
            return val > x.val;
        }
    }Node;
    const int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
    
    int BFS(int n){
        priority_queue<Node> Q;
        Node t;
        memset(visit,0,sizeof(visit));
        int x=0,y=0,goalx=n-1,goaly=n-1,newx,newy;
        t=(Node){x,y,mat[x][y]};
        visit[x][y] = true;
        Q.push(t);
        while(!Q.empty()){
            t = Q.top();Q.pop();
            if(t.x == goalx && t.y == goaly) return t.val;
            for(int d=0;d<4;d++){
                newx = t.x + dir[d][0];
                newy = t.y + dir[d][1];
                if(newx>=0 && newx<n && newy>=0 && newy<n && mat[newx][newy] && !visit[newx][newy]){
                    visit[newx][newy] = true;
                    Q.push((Node){newx,newy,t.val+mat[newx][newy]});
                }
            }
        }
        return -1;
    }
    
    void Input_data(int n){
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){
            scanf("%d",&mat[i][j]);
        }
    }
    
    int main(){
        int n;
        while(scanf("%d",&n)==1){
            Input_data(n);
            printf("min=%d
    ",BFS(n));
        }
    }
    

    BFS更改步数法:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    
    using namespace std;
    
    const int N = 100+5;
    const int MaxSize = 1e5;
    const int INF = (1<<30);
    int mat[N][N];
    int Min[N][N];
    typedef struct node{
        int x,y,val;
        bool operator < (const node x) const {
            return val > x.val;
        }
    }Node;
    const int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
    int BFS(int n){
       priority_queue<Node> Q;
       int newx,newy,x=0,y=0,goalx= n-1,goaly=n-1;
       Node t,s;
       t.x = x,t.y = y,t.val = mat[0][0];
       Min[x][y] = mat[x][y];
       Q.push(t);
       while(true){
            t = Q.top();
            if(t.x == goalx && t.y == goaly ) return t.val;
            for(int d=0;d<4;d++){
                newx = t.x+dir[d][0];
                newy = t.y+dir[d][1];
                if(newx>=0 && newx<n && newy>=0 && newy<n && mat[newx][newy]){
                    if(t.val + mat[newx][newy] < Min[newx][newy]){
                    s.x = newx,s.y = newy,s.val = t.val+mat[newx][newy];
                    Min[newx][newy] = s.val;
                    Q.push(s);
                    }
                }
            }
            Q.pop();
        }
    }
    
    void Init(){
        for(int i=0;i<N;i++)
            for(int j=0;j<N;j++){
            Min[i][j] = INF;
            }
    }
    
    void Input_data(int n){
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            scanf("%d",&mat[i][j]);
    }
    
    int main(){
        int n;
        //freopen("1.out","r",stdin);
        while(scanf("%d",&n)==1){
        Init();
        Input_data(n);
        printf("min=%d
    ",BFS(n));
        }
    }
    

    建图跑迪杰斯特拉:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define _cp(a,b)((a.val)<(b.val))
    
    using namespace std;
    
    const int MAXN = 100000;
    const int INF = (1<<30);
    const int N = 100 + 5;
    int mat[N][N],D[N*N];
    bool visit[N*N];
    int Size[N*N];
    typedef struct node{
        short val,to;
    }Node;
    typedef Node elem_t;
    Node edge[N*N][4];
    const int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
    void Init(){
        for(int i=0;i<N*N;i++){
                Size[i] = 0;
            visit[i] = false;
            D[i] = INF;
        }
    }
    void build_mat(int n){
        Node t;
        int to,newx,newy,from;
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){
            from = i*n+j;
            for(int d=0;d<4;d++){
                newx = i + dir[d][0];
                newy = j + dir[d][1];
                if(newx>=0 && newx<n && newy>=0 && newy<n && mat[newx][newy]){
                    to = newx*n+newy;
                    int & cnt = Size[from];
                    t.to = to,t.val=mat[newx][newy];
                    edge[from][cnt++] = t;
                }
            }
        }
    }
    struct heap{
        elem_t h[MAXN];
        int n,p,c;
        void init(){n=0;}
        void ins(elem_t e){
            for(p=++n;p>1 && _cp(e,h[p>>1]);h[p]=h[p>>1],p>>=1);
            h[p] = e;
        }
        int del(elem_t &e){
            if(!n) return 0;
            for(e=h[p=1],c=2;c<n && _cp(h[c+=(c<n-1 &&_cp(h[c+1],h[c]))],h[n]);h[p] = h[c],p=c,c<<=1);
            h[p] = h[n--]; return 1;
        }
    };
    int DIJ(int n){
        heap H;
        H.init();
        D[0] = 0;
        Node t;
        int u,v;
        t.to = 0,t.val = 0;
        H.ins(t);
        while(H.del(t)){
            u = t.to;
            visit[u] = true;
            if(D[u] < t.val) continue;
            for(int j=0; j<Size[u]; j++){
                v = edge[u][j].to;
                if(visit[v]) continue;
                if(D[v] > D[u] + edge[u][j].val){
                    D[v] = D[u] +edge[u][j].val;
                    t.to = v,t.val = D[v];
                    H.ins(t);
                }
            }
        }
        return D[n*n-1] + mat[0][0];
    }
    void Input_data(int n){
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){
            scanf("%d",&mat[i][j]);
        }
    }
    int main(){
        int n;
        while(scanf("%d",&n)==1){
            Init();
            Input_data(n);
            build_mat(n);
            printf("min=%d
    ",DIJ(n));
        }
    }
    

    双向BFS:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    
    using namespace std;
    
    const int N = 100+5;
    const int MaxSize = 1e5;
    const int INF = (1<<30);
    int mat[N][N];
    struct visit{
        int val,vis;
    }Min[N][N];
    
    typedef struct node{
        int x,y,val;
        bool operator < (const node x) const {
            return val > x.val;
        }
    }Node;
    
    const int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
    
    int BFS(int n){
       priority_queue<Node> Q1,Q2;
       int newx,newy,cnt,x=0,y=0,goalx= n-1,goaly=n-1,ans = INF;
       Node t,s;
       t.x = x,t.y = y,t.val = mat[0][0];
       s.x = goalx,s.y = goaly,s.val = mat[goalx][goaly];
       Min[x][y].vis = 1,Min[x][y].val = mat[x][y];
       Min[goalx][goaly].vis = 2,Min[goalx][goaly].val = mat[goalx][goaly];
       Q1.push(t);
       Q2.push(s);
       while(!Q1.empty()|| !Q2.empty()){
        cnt = Q1.size();
        while(cnt--){
            t = Q1.top(); Q1.pop();
            if(t.x == goalx && t.y == goaly ) ans = min(ans,t.val);         //这里一定要注意,要拓展完才能确定最小值,不能相遇就跳出
            for(int d=0;d<4;d++){
                newx = t.x+dir[d][0];
                newy = t.y+dir[d][1];
                if(newx>=0 && newx<n && newy>=0 && newy<n){
                    if(Min[newx][newy].vis==2) ans = min(t.val + Min[newx][newy].val,ans);
                    if(t.val + mat[newx][newy] < Min[newx][newy].val){
                    s.x = newx,s.y = newy,s.val = t.val+mat[newx][newy];
                    Min[newx][newy].val = s.val;
                    Min[newx][newy].vis = 1;
                    Q1.push(s);
                    }
                }
            }
        }
       cnt = Q2.size();
        while(cnt--){
            t = Q2.top();Q2.pop();
            if(t.x == x && t.y == y) return t.val;
            for(int d=0;d<4;d++){
                newx = t.x + dir[d][0];
                newy = t.y + dir[d][1];
                if(newx>=0 && newx<n && newy>=0 && newy<n ){
                    if(Min[newx][newy].vis==1) ans = min(t.val + Min[newx][newy].val,ans);
                    if(t.val + mat[newx][newy] < Min[newx][newy].val){
                        s.x = newx,s.y = newy,s.val = t.val + mat[newx][newy];
                        Min[newx][newy].val = s.val;
                        Min[newx][newy].vis = 2;
                        Q2.push(s);
                    }
                }
            }
        }
    
       }
       return ans;
    }
    
    void Init(){
        for(int i=0;i<N;i++)
            for(int j=0;j<N;j++){
            Min[i][j].val = INF;
            Min[i][j].vis = 0;
            }
    }
    
    void Input_data(int n){
        int val;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++){
            scanf("%d",&val);
            mat[i][j] = val?val:INF;
            }
    }
    
    int main(){
        int n;
        //freopen("1.out","r",stdin);
        while(scanf("%d",&n)==1){
        Init();
        Input_data(n);
        printf("min=%d
    ",BFS(n));
        }
    }
    //如有错误,还请指出

    在这几种方法里,双向BFS和迪杰斯特拉耗时都是12ms,比其他两种BFS耗时都短,虽然说在这里使用迪杰斯特拉有点大材小用的意味,但是这种方法也去可以应用到其他问题上

  • 相关阅读:
    hadoop机架感知
    Ajax请求结果的缓存
    Blocks语法
    CentOS yum 源的配置与使用
    .NET三层架构开发初步
    Mac技巧合集第一期
    Fine Uploader文件上传组件
    WCF 系列文章
    http权威指南读书笔记
    WCF Service Hosting的线程关联性Mono实现比.NET统一?
  • 原文地址:https://www.cnblogs.com/Pretty9/p/7347724.html
Copyright © 2020-2023  润新知