zoukankan      html  css  js  c++  java
  • UVA-1601

    The Morning after Halloween(UVA-1601)

    Problem:https://vjudge.net/problem/UVA-1601

    Input:

    5 5 2
    #####
    #A#B#
    #   #
    #b#a#
    #####
    16 4 3
    ################
    ## ########## ##
    #    ABCcba    #
    ################
    16 16 3
    ################
    ### ##    #   ##
    ##  #  ##   # c#
    #  ## ########b#
    # ##  # #   #  #
    #  # ##   # # ##
    ##  a#  # # #  #
    ### ## #### ## #
    ##   #   #  #  #
    #  ##### # ## ##
    ####   #B# #   #
    ##  C#   #   ###
    #  # # ####### #
    # ######  A##  #
    #        #    ##
    ################
    0 0 0
    

    Output:

    7
    36
    77
    

    Solution:

    双向bfs经典题,这题的核心算法就是双向bfs,但是对于本题的优化是非常有趣的。在题中提出了没个2*2的方块里至少一个墙壁,所以可通行的地方最多有75%的方格,如果我们直接去搜图中的点,那么每个点需要检验五个状态,同时又有三个鬼,所以要遍历(5^3)种也就是125个,同时有((16 *16)^3)种状态也就是(256^3)种,显然是会超时的,所以有如下优化:

    1. 我们把每个点的可通行位置提取出来构成一张无向图,在这张图上跑bfs,每次我们只需要遍历可 以到达的点。
    2. 对所有的空白格编号,搜索针对编号处理。
    3. 双向bfs搜索,提高搜索效率
    4. 对每种状态可知,之多有三个鬼分布在图的不同位置,每个数最大为192(图上空白格数,实际会更小),所以应一个三位的192进制数表示即可(整数哈希)。

    代码实际写起来会有些不好处理的地方,由于本人较菜,所以代码比较长。大佬可以自行优化orz。

    Code:

    /**********************************************************
    * @Author: 			   Kirito
    * @Last Modified by:   Kirito
    * @Remark:
    **********************************************************/
    #include <bits/stdc++.h>
    #define lowbit(x) (x&(-x))
    #define CSE(x,y) memset(x,y,sizeof(x))
    #define INF 0x3f3f3f3f
    #define Abs(x) (x>=0?x:(-x))
    #define FAST ios::sync_with_stdio(false);cin.tie(0);
    #define debug(x) cout<<#x<<"------"<<x<<endl
    using namespace std;
    
    typedef long long ll;
    typedef pair<int,int> pii;
    typedef pair<ll , ll> pll;
    
    const int MAXN=31;
    const int mv[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    int w,h,n;
    string str[MAXN];
    pii ls[MAXN*MAXN];
    int cnt;
    vector<int> gp[202];
    
    struct node{
        int ad0,ad1,ad2;
        int step;
        node(int x=0,int y=0,int z=0,int d=1):ad0(x),ad1(y),ad2(z),step(d){}
    
        int getHash(){
            return ad0+ad1*256+ad2*256*256;
        }
    }be,ed;
    
    int vis[8000000],vit[8000000];
    int bfs()
    {
        queue<node> box,que;
        if(be.getHash()==ed.getHash()) return 0;
        vis[be.getHash()]=1;
        vit[ed.getHash()]=1;
        box.push(be);que.push(ed);
        while(!box.empty()&&!que.empty()){
            if(box.size()<que.size()){
                int ok=box.front().step;
                while(!box.empty()&&ok==box.front().step){
                    node now=box.front();
                    box.pop();
                    for(auto i:gp[now.ad0]){
                        if(n>1){
                            for(auto j:gp[now.ad1]){
                                if(i==j) continue;
                                if(i==now.ad1&&j==now.ad0) continue;
                                if(n>2){
                                    for(auto k:gp[now.ad2]){
                                        if(i==k||j==k) continue;
                                        if(i==now.ad2&&k==now.ad0) continue;
                                        if(j==now.ad2&&k==now.ad1) continue;
                                        node nxt=node(i,j,k,now.step+1);
                                        int hh=nxt.getHash();
                                        if(vis[hh]) continue;
                                        if(vit[hh]){
                                            return nxt.step+vit[hh]-2;
                                        }
                                        vis[hh]=nxt.step;
                                        box.push(nxt);
                                    }
                                }
                                else{
                                    node nxt=node(i,j,0,now.step+1);
                                    int hh=nxt.getHash();
                                    if(vis[hh]) continue;
                                    if(vit[hh]){
                                        return nxt.step+vit[hh]-2;
                                    }
                                    vis[hh]=nxt.step;
                                    box.push(nxt);
                                }
                            }
                        }
                        else{
                            node nxt=node(i,0,0,now.step+1);
                            int hh=nxt.getHash();
                            if(vis[hh]) continue;
                            if(vit[hh]){
                                return nxt.step+vit[hh]-2;
                            }
                            vis[hh]=nxt.step;
                            box.push(nxt);
                        }
                    }
                }
            }
            else{
                int ok=que.front().step;
                while(!que.empty()&&ok==que.front().step){
                    node now=que.front();
                    que.pop();
                    for(auto i:gp[now.ad0]){
                        if(n>1){
                            for(auto j:gp[now.ad1]){
                                if(i==j) continue;
                                if(i==now.ad1&&j==now.ad0) continue;
                                if(n>2){
                                    for(auto k:gp[now.ad2]){
                                        if(i==k||j==k) continue;
                                        if(i==now.ad2&&k==now.ad0) continue;
                                        if(j==now.ad2&&k==now.ad1) continue;
                                        node nxt=node(i,j,k,now.step+1);
                                        int hh=nxt.getHash();
                                        if(vit[hh]) continue;
                                        if(vis[hh]){
                                            return nxt.step+vis[hh]-2;
                                        }
                                        vit[hh]=nxt.step;
                                        que.push(nxt);
                                    }
                                }
                                else{
                                    node nxt=node(i,j,0,now.step+1);
                                    int hh=nxt.getHash();
                                    if(vit[hh]) continue;
                                    if(vis[hh]){
                                        return nxt.step+vis[hh]-2;
                                    }
                                    vit[hh]=nxt.step;
                                    que.push(nxt);
                                }
                            }
                        }
                        else{
                            node nxt=node(i,0,0,now.step+1);
                            int hh=nxt.getHash();
                            if(vit[hh]) continue;
                            if(vis[hh]){
                                return nxt.step+vis[hh]-2;
                            }
                            vit[hh]=nxt.step;
                            que.push(nxt);
                        }
                    }
                }
            }
        }
        return -1;
    }
    
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("in.in","r",stdin);
    	#endif
        while(cin>>w>>h>>n){
            if(w==0&&h==0&&n==0) break;
            cin.get();
            for(int i=0;i<h;i++){
                getline(cin,str[i]);
            }
            cnt=0;
            be=node();ed=node();
            ls[cnt++]=make_pair(0,0);
            for(int i=0;i<h;i++){
                for(int j=0;j<w;j++){
                    if(str[i][j]!='#'){
                        ls[cnt++]=make_pair(i,j);
                    }
                }
            }
            sort(ls,ls+cnt);
            for(int i=0;i<200;i++)
                gp[i].clear();
            for(int i=0;i<h;i++){
                for(int j=0;j<w;j++){
                    if(str[i][j]!='#'){
                        int u=int(lower_bound(ls,ls+cnt,make_pair(i,j))-ls);
                        if(str[i][j]>='A'&&str[i][j]<='Z'){
                            int m=int(str[i][j]-'A');
                            if(m==0) ed.ad0=u;
                            else if(m==1) ed.ad1=u;
                            else ed.ad2=u;
                        }
                        if(str[i][j]>='a'&&str[i][j]<='z'){
                            int m=int(str[i][j]-'a');
                            if(m==0) be.ad0=u;
                            else if(m==1) be.ad1=u;
                            else be.ad2=u;
                        }
                        gp[u].push_back(u);
                        for(int k=0;k<4;k++){
                            int nx=i+mv[k][0];
                            int ny=j+mv[k][1];
                            if(nx>=0&&nx<h&&ny>=0&&ny<w&&str[nx][ny]!='#'){
                                int v=int(lower_bound(ls,ls+cnt,make_pair(nx,ny))-ls);
                                gp[u].push_back(v);
                            }
                        }
                    }
                }
            }
            CSE(vis,0);CSE(vit,0);
            cout<<bfs()<<endl;
        }
    	return 0;
    }
    

    我这份代码跑了560ms,算是比较快的了

  • 相关阅读:
    什么是UDDI?
    保存图片
    什么是EIP?
    众多Android开源项目推荐
    Google code android 开源项目 集合
    实现屏幕下方展示的TAB分页
    Android中attr 自定义 属性详解
    J2EE快速开发框架wabacus
    popwindow动画显示消失,activity切换动画
    Android 一些项目的源代码,覆盖Android开发的每个领域
  • 原文地址:https://www.cnblogs.com/LeafLove/p/13647364.html
Copyright © 2011-2022 走看看