• Uva 1061 The Morning after Halloween


    基本思路是BFS:

      1. 题目中已经说了,每相连的2X2格子中必有一个‘#’,也就是,每个点周围最多也就三个方向可以走。因此,可以把所有空格都提出来,形成一个图,直接遍历每条边,而不是每次判断4个方向是否可以走

      2.关于结点判重,最初的想法是想用一个六维数组,后来参考了其它,发现其实可以用一个三维数字代替,每个点可以用数字代替,因为题目中整个图最多为16X16,所以数字最大为16*16 = 256,这样做的另一个好处是,移动字母也方便了,可以用数字代替点,比如从(0, 0)移动到(0,1)可以考做是从 0 移动到 1

      3.N的数量不一,移动时要不要判断是N是多少?这是我刚开始的想法,个人采用递归的方法,先放一个点,再放下一个点,观察这是不是最后一个要移动的点,相对而言,比对每个N值进行单独处理要简单点。

    注意点:题目输入的W,H,N中W是指宽度,即列数,而H即为行数。

    收获及感悟:刚开始看到这题的时候已经吓着了,首先就是如何保存三个点状态,真的差点用六维数组或map了。在这里也学了一招,用整数依次标记每个点。另外,关于题意,刚开始理解不透,还在想a,b,c三者的先后移动顺序,后来发现想多了,任意顺序移动,判断移动后的状态是否可行即可。这题是在看了别人代码后才A掉的,非常感谢发布题解的同学。

    参考资料:

      1.http://blog.csdn.net/acm_hkbu/article/details/42420503

      2.《算法竞赛入门经典(第2版)》

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int MAXN = 16 + 5;
    char plan[MAXN][MAXN];
    int W, H, N;
    vector<int> link[MAXN*MAXN];
    bool vis[MAXN*MAXN][MAXN*MAXN][MAXN*MAXN];
    int dir[4][2] = {0,1, 0,-1, 1,0, -1,0};
    
    struct State{
        int ghostPos[5], step;
    };
    
    State finalState, firstState;
    
    // more than one ghost occupy a same position
    // p is the prev state, whether two ghots in s exchange with their position
    bool isCollisionOrExChange(State& s, State& p) {
        for(int i=0; i<N; ++i) {
            for(int j=0; j<N; ++j) {
                if(i!=j && s.ghostPos[i] == s.ghostPos[j]) {
                    return true;
                }
                if(i!=j && s.ghostPos[i] == p.ghostPos[j] && s.ghostPos[j] == p.ghostPos[i]) {
                    return true;
                }
            }
        }
        return false;
    }
    
    void Read() {
        for(int i=0; i<H; ++i) {
            cin.get();
            for(int j=0; j<W; ++j) {
                plan[i][j] = cin.get();
            }
        }
    }
    
    int GetVisValue(int x, int y) {
        return x * W + y;
    }
    
    void SetVis(State& t, bool flag) {
        int i, a[3]; // the positon of each ghost
        for(i=0; i<N; ++i) {
            a[i] = t.ghostPos[i];
        }
        // the number of ghosts may be less than 3
        for(; i<3; ++i) {
            a[i] = 0;
        }
        vis[a[0]][a[1]][a[2]] = flag;
    }
    
    bool IsVis(State& t) {
        int i, a[3]; // the positon of each ghost
        for(i=0; i<N; ++i) {
            a[i] = t.ghostPos[i];
        }
        // the number of ghosts may be less than 3
        for(; i<3; ++i) {
            a[i] = 0;
        }
        return vis[a[0]][a[1]][a[2]];
    }
    
    bool IsFinal(State& t) {
        for(int i=0; i<N; ++i) {
            if(finalState.ghostPos[i] != t.ghostPos[i]) {
                return false;
            }
        }
        return true;
    }
    
    // the ghost numbered g move
    void NextState(State& s, int g, queue<State>& q, State& former) {
        for(size_t i=0; i<link[former.ghostPos[g]].size(); ++ i) {
            s.ghostPos[g] = link[former.ghostPos[g]][i];
            if(g == N-1 && !IsVis(s) && !isCollisionOrExChange(s, former)) {
                SetVis(s, true);
                q.push(s);
            } else if (g < N-1) {
                NextState(s, g+1, q, former);
            }
        }
    }
    
    // output the point of all ghosts
    void Test(State& t) {
        for(int i=0; i<N; ++i) {
            cout << t.ghostPos[i] / W << " " << t.ghostPos[i] % W << endl;
        }
        cout << t.step << endl;
        cout << endl;
    }
    
    int Bfs() {
        memset(vis, false, sizeof(vis));
        queue<State> q;
        firstState.step = 0;
        q.push(firstState);
        SetVis(firstState, true);
        while(!q.empty()) {
            State t = q.front();
            q.pop();
            // Test(t);
            if(IsFinal(t)) {
                return t.step;
            }
            State newS;
            newS.step = t.step + 1;
            NextState(newS, 0, q, t);
        }
        return -1;
    }
    
    // Make a Graph
    void MakeLink() {
        for(int i=0; i<H; ++ i) {
            for(int j=0; j<W; ++ j) {
                if(plan[i][j] != '#') {
                    // the position means unmoving
                    link[GetVisValue(i, j)].clear();
                    link[GetVisValue(i, j)].push_back(GetVisValue(i, j));
                    for(int k=0; k<4; ++k) { // four directions
                        int x = i + dir[k][0];
                        int y = j + dir[k][1];
                        if(x>=0 && x<H && y>=0 && y<W && plan[x][y]!='#') {
                            link[GetVisValue(i, j)].push_back(GetVisValue(x, y));
                        }
                    }
                }
                if (isupper(plan[i][j])) {
                    finalState.ghostPos[plan[i][j]-'A'] = GetVisValue(i, j);
                } else if (islower(plan[i][j])) {
                    firstState.ghostPos[plan[i][j]-'a'] = GetVisValue(i, j);
                }
            }
        }
    }
    
    void Work() {
        Read();
        MakeLink();
        cout << Bfs() << endl;
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0);
        while(cin >> W >> H >> N) {
            if(!W && !H && !N) {
                break;
            }
            Work();
        }
        return 0;
    }
    

      

  • 相关阅读:
    java线程池笔记
    java多线程简单用法
    Java 常用工具类整理
    Linux nohup命令详解
    Java八种基本类型
    isms项目tomcat运行配置
    2017计划
    ES6 Reflect 与 Proxy
    ES6 Map与Set
    ES6 Symbol类型
  • 原文地址:https://www.cnblogs.com/Emerald/p/4721890.html
Copyright © 2020-2023  润新知