zoukankan      html  css  js  c++  java
  • UVA-1601 The Morning after Halloween(BFS或双向BFS)

    题目大意:在一张图中,以最少的步数将a,b,c移到对应的A,B,C上去。其中,每个2x2的方格都有障碍并且不能两个小写字母同时占据一个格子。

    题目分析:为避免超时,先将图中所有能联通的空格建起一张图,然后再BFS。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<queue>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    
    struct Node
    {
        int t,now[3];
        Node(int _t,int a=-1,int b=-1,int c=-1):t(_t){now[0]=a,now[1]=b,now[2]=c;}
        bool operator < (const Node &a) const {
            return t>a.t;
        }
    };
    struct Edge
    {
        int to,nxt;
    };
    Edge e[2000];
    char mp[17][17];
    int w,h,n,cnt,head[267];
    int goal[3],start[3],vis[268][268][268];
    int d[5][2]={{0,0},{-1,0},{1,0},{0,1},{0,-1}};
    
    void add(int u,int v)
    {
        e[cnt].to=v;
        e[cnt].nxt=head[u];
        head[u]=cnt++;
    }
    
    void init()
    {
        cnt=0;
        memset(start,-1,sizeof(start));
        memset(goal,-1,sizeof(goal));
        memset(head,-1,sizeof(head));
        for(int i=0;i<h;++i){
            for(int j=0;j<w;++j){
                if(mp[i][j]=='#')
                    continue;
                if(mp[i][j]>='a'&&mp[i][j]<='c')
                    start[mp[i][j]-'a']=i*w+j;
                if(mp[i][j]>='A'&&mp[i][j]<='C')
                    goal[mp[i][j]-'A']=i*w+j;
                for(int k=0;k<5;++k){
                    int ni=i+d[k][0],nj=j+d[k][1];
                    if(ni>=0&&ni<h&&nj>=0&&nj<w&&mp[ni][nj]!='#')
                        add(i*w+j,ni*w+nj);
                }
            }
        }
    }
    
    bool ok(const Node &u)
    {
        for(int i=0;i<n;++i)
            if(u.now[i]!=goal[i])
                return false;
        return true;
    }
    
    int bfs()
    {
        priority_queue<Node>q;
        memset(vis,0,sizeof(vis));
        vis[start[0]+10][start[1]+10][start[2]+10]=1;
        q.push(Node(0,start[0],start[1],start[2]));
        while(!q.empty())
        {
            Node u=q.top();
            q.pop();
    
            if(ok(u))
                return u.t;
            if(n==1){
                for(int i=head[u.now[0]];i!=-1;i=e[i].nxt){
                    Node nxt=u;
                    nxt.now[0]=e[i].to;
                    if(vis[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10])    continue;
                    vis[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10]=1;
                    nxt.t=u.t+1;
                    q.push(nxt);
                }
            }else if(n==2){
                for(int i=head[u.now[0]];i!=-1;i=e[i].nxt){
                    Node nxt=u;
                    nxt.now[0]=e[i].to;
                    for(int j=head[u.now[1]];j!=-1;j=e[j].nxt){
                        nxt.now[1]=e[j].to;
                        if(nxt.now[0]==nxt.now[1])  continue;
                        if(nxt.now[0]==u.now[1]&&nxt.now[1]==u.now[0])    continue;
                        if(vis[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10])    continue;
                        vis[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10]=1;
                        nxt.t=u.t+1;
                        q.push(nxt);
                    }
                }
            }else{
                for(int i=head[u.now[0]];i!=-1;i=e[i].nxt){
                    Node nxt=u;
                    nxt.now[0]=e[i].to;
                    for(int j=head[u.now[1]];j!=-1;j=e[j].nxt){
                        nxt.now[1]=e[j].to;
                        if(nxt.now[0]==nxt.now[1])  continue;
                        if(nxt.now[0]==u.now[1]&&nxt.now[1]==u.now[0])    continue;
                        for(int k=head[u.now[2]];k!=-1;k=e[k].nxt){
                            nxt.now[2]=e[k].to;
                            if(nxt.now[2]==nxt.now[0]||nxt.now[2]==nxt.now[1])  continue;
                            if(nxt.now[2]==u.now[0]&&nxt.now[0]==u.now[2])  continue;
                            if(nxt.now[2]==u.now[1]&&nxt.now[1]==u.now[2])  continue;
                            if(vis[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10])    continue;
                            vis[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10]=1;
                            nxt.t=u.t+1;
                            q.push(nxt);
                        }
                    }
                }
            }
        }
    }
    
    int main()
    {
        while(scanf("%d%d%d",&w,&h,&n)&&(w+h+n))
        {
            getchar();
            for(int i=0;i<h;++i)
                gets(mp[i]);
            init();
            printf("%d
    ",bfs());
        }
        return 0;
    }
    

      

    这道题已知结束状态,还可以使用双向BFS(个人感觉使用双向BFS的效率提升的并不是多明显,从2002ms提到1189ms,也可能是我的代码写得比较挫吧!!!)。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<queue>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    
    struct Node
    {
        int t,now[3];
        Node(int _t,int a=-1,int b=-1,int c=-1):t(_t){now[0]=a,now[1]=b,now[2]=c;}
        bool operator < (const Node &a) const {
            return t>a.t;
        }
    };
    struct Edge
    {
        int to,nxt;
    };
    Edge e[2000];
    char mp[17][17];
    int w,h,n,cnt,head[267],mark[268][268][268];
    int goal[3],start[3],vis[268][268][268];
    int d[5][2]={{0,0},{-1,0},{1,0},{0,1},{0,-1}};
    priority_queue<Node>q[2];
    
    void add(int u,int v)
    {
        e[cnt].to=v;
        e[cnt].nxt=head[u];
        head[u]=cnt++;
    }
    
    void init()
    {
        cnt=0;
        memset(start,-1,sizeof(start));
        memset(goal,-1,sizeof(goal));
        memset(head,-1,sizeof(head));
        for(int i=0;i<h;++i){
            for(int j=0;j<w;++j){
                if(mp[i][j]=='#')
                    continue;
                if(mp[i][j]>='a'&&mp[i][j]<='c')
                    start[mp[i][j]-'a']=i*w+j;
                if(mp[i][j]>='A'&&mp[i][j]<='C')
                    goal[mp[i][j]-'A']=i*w+j;
                for(int k=0;k<5;++k){
                    int ni=i+d[k][0],nj=j+d[k][1];
                    if(ni>=0&&ni<h&&nj>=0&&nj<w&&mp[ni][nj]!='#')
                        add(i*w+j,ni*w+nj);
                }
            }
        }
    }
    
    int bfs(int id,int step)
    {
        while(!q[id].empty()){
            Node u=q[id].top();
            if(u.t!=step)
                return -1;
            q[id].pop();
    
            if(n==1){
                for(int i=head[u.now[0]];i!=-1;i=e[i].nxt){
                    Node nxt=u;
                    nxt.now[0]=e[i].to;
                    if(vis[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10]==-1){
                        vis[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10]=id;
                        mark[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10]=u.t+1;
                        nxt.t=u.t+1;
                        q[id].push(nxt);
                    }else if(vis[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10]==!id)
                        return u.t+1+mark[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10];
                }
            }else if(n==2){
                for(int i=head[u.now[0]];i!=-1;i=e[i].nxt){
                    Node nxt=u;
                    nxt.now[0]=e[i].to;
                    for(int j=head[u.now[1]];j!=-1;j=e[j].nxt){
                        nxt.now[1]=e[j].to;
                        if(nxt.now[0]==nxt.now[1])  continue;
                        if(nxt.now[0]==u.now[1]&&nxt.now[1]==u.now[0])    continue;
                        if(vis[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10]==-1){
                            vis[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10]=id;
                            mark[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10]=u.t+1;
                            nxt.t=u.t+1;
                            q[id].push(nxt);
                        }else if(vis[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10]==!id)
                            return u.t+1+mark[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10];
                    }
                }
            }else{
                for(int i=head[u.now[0]];i!=-1;i=e[i].nxt){
                Node nxt=u;
                    nxt.now[0]=e[i].to;
                    for(int j=head[u.now[1]];j!=-1;j=e[j].nxt){
                        nxt.now[1]=e[j].to;
                        if(nxt.now[0]==nxt.now[1])  continue;
                        if(nxt.now[0]==u.now[1]&&nxt.now[1]==u.now[0])    continue;
                        for(int k=head[u.now[2]];k!=-1;k=e[k].nxt){
                            nxt.now[2]=e[k].to;
                            if(nxt.now[2]==nxt.now[0]||nxt.now[2]==nxt.now[1])  continue;
                            if(nxt.now[2]==u.now[0]&&nxt.now[0]==u.now[2])  continue;
                            if(nxt.now[2]==u.now[1]&&nxt.now[1]==u.now[2])  continue;
                            if(vis[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10]==-1){
                                vis[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10]=id;
                                mark[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10]=u.t+1;
                                nxt.t=u.t+1;
                                q[id].push(nxt);
                            }else if(vis[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10]==!id)
                                return u.t+1+mark[nxt.now[0]+10][nxt.now[1]+10][nxt.now[2]+10];
                        }
                    }
                }
            }
        }
        return -1;
    }
    
    int solve()
    {
        while(!q[0].empty())
            q[0].pop();
        while(!q[1].empty())
            q[1].pop();
        memset(vis,-1,sizeof(vis));
        memset(mark,0,sizeof(mark));
        vis[start[0]+10][start[1]+10][start[2]+10]=0;
        vis[goal[0]+10][goal[1]+10][goal[2]+10]=1;
        q[0].push(Node(0,start[0],start[1],start[2]));
        q[1].push(Node(0,goal[0],goal[1],goal[2]));
        int step=0;
        while(!q[0].empty()||!q[1].empty()){
            if(!q[0].empty()){
                int k=bfs(0,step);
                if(k!=-1)
                    return k;
            }
            if(!q[1].empty()){
                int k=bfs(1,step);
                if(k!=-1)
                    return k;
            }
            ++step;
        }
        return -1;
    }
    
    int main()
    {
        while(scanf("%d%d%d",&w,&h,&n)&&(w+h+n))
        {
            getchar();
            for(int i=0;i<h;++i)
                gets(mp[i]);
            init();
            printf("%d
    ",solve());
        }
        return 0;
    }
    

      

  • 相关阅读:
    Docker虚拟机配置手札(centos)
    Nginx配置手札
    登录的顶号功能实现
    苹果登录服务端JWT算法验证-PHP
    mac Read-Only filesystem (转载)
    ssh公私钥登录/git公私钥认证
    crontab 定时访问指定url,定时脚本
    网站通用 敏感词列表
    游戏行业术语一览(2)--游戏运营转化率[转载]
    <转载>为什么VR不可能成功?
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/4844828.html
Copyright © 2011-2022 走看看