1215. 脱离地牢

解题技巧:1.广度优先搜索

     2.分离地图和人物位置状态

     3.压缩人物位置状态为一个整数,以便去掉重复的状态

#include <cstdio>
#include <set>
#include <map>
#include <queue>
using namespace std;

struct Cor {
    int r, c;
    Cor(int r_ = 0, int c_ = 0) : r(r_), c(c_) {}
    Cor operator+(const Cor &cor) {
        return Cor(r + cor.r, c + cor.c);
    }
    Cor& operator=(const Cor &cor) {
        r = cor.r;
        c = cor.c;
        return *this;
    }
    bool operator==(const Cor&cor) {
        return r == cor.r && c == cor.c;
    }
};

struct State {
    Cor h, p;
    State() {}
};

struct Map {
    static const int maxr = 20;
    static const int maxc = 20;
    static const int maxd = 4;

    static const int HR = 1;
    static const int HC = 100;
    static const int PR = 10000;
    static const int PC = 1000000;

    static const int max_step = 255;

    char m[maxr][maxc+1];
    char p_d[maxd + 1];
    char h_d[maxd + 1];
    int rows, cols;

    queue<State> state_queue;

    map<char, Cor> d_x;
    set<int> ids;

    bool success;
    int step;

    void init() {
        d_x.insert(make_pair(‘N‘, Cor(-1, 0)));
        d_x.insert(make_pair(‘S‘, Cor(1, 0)));
        d_x.insert(make_pair(‘W‘, Cor(0, -1)));
        d_x.insert(make_pair(‘E‘, Cor(0, 1)));
        p_d[0] = ‘N‘; p_d[1] = ‘S‘; p_d[2] = ‘W‘; p_d[3] = ‘E‘;
        while (!state_queue.empty()) state_queue.pop();
    }

    void input() {
        scanf("%d%d", &rows, &cols);
        for (int r = 0; r < rows; ++r)
            scanf("%s", m[r]);
        scanf("%s", h_d);
    }

    int makeId(const State & state) {
        return state.h.r * HR + state.h.c * HC + state.p.r * PR + state.p.c * PC;
    }

    void extractHP() {
        State state;
        for (int r = 0; r < rows; ++r) {
            for (int c = 0; c < cols; ++c) {
                if (m[r][c] == ‘H‘) {
                    state.h.r = r;
                    state.h.c = c;
                    m[r][c] = ‘.‘;
                } else if (m[r][c] == ‘P‘) {
                    state.p.r = r;
                    state.p.c = c;
                    m[r][c] = ‘.‘;
                }
            }
        }
        int id = makeId(state);
        ids.insert(id);
        state_queue.push(state);
    }

    void solve() {
        success = false;
        step = 0;
        while (!state_queue.empty() && step < max_step && !success) {
            ++step;
            int size = state_queue.size();
            while (size-- && !success) {
                State &state = state_queue.front();

                for (int i = 0; i < maxd; ++i) {
                    Cor & p_d_cor = d_x[p_d[i]];
                    Cor & h_d_cor = d_x[h_d[i]];
                    State next_state;
                    next_state.h = state.h + h_d_cor;
                    if (m[next_state.h.r][next_state.h.c] == ‘#‘) {
                        next_state.h = state.h;
                    } else if (m[next_state.h.r][next_state.h.c] == ‘!‘) {
                        continue;
                    }
                    next_state.p = state.p + p_d_cor;
                    if (m[next_state.p.r][next_state.p.c] == ‘#‘) {
                        continue;
                    } else if (m[next_state.p.r][next_state.p.c] == ‘!‘) {
                        continue;
                    }
                    if ((next_state.h == next_state.p) || (next_state.h == state.p && next_state.p == state.h)) {
                        // 达到目的地
                        success = true;
                        break;
                    }
                    int id = makeId(next_state);
                    if (ids.find(id) == ids.end()) {
                        ids.insert(id);
                        state_queue.push(next_state);
                    }
                }

                state_queue.pop();
            }
        }
    }

};

int main() {
    Map mp;
    mp.init();
    mp.input();
    mp.extractHP();
    mp.solve();
    if (mp.success) {
        printf("%d\n", mp.step);
    } else {
        printf("%s\n", "Impossible");
    }
    return 0;
}

  

时间: 2024-10-06 04:25:41

1215. 脱离地牢的相关文章

sicily 1215 脱离地牢

做Sicily 1215脱离地牢 这一题,一直Restrict function,都快崩溃了. 最后发现是内存泄露,就是new出来的东西没有及时delete导致的. 具体是在广度优先搜索的时候,每找一次邻居就new出一些节点,有些节点已被visited了然后我直接忽略它们,实际上是得把它们delete掉的,还有就是pop出一个节点后,在处理完邻居之后要把这个节点delete了 贴个代码片段: 第32,35行便是要注意的地方. 运行效率:0秒,312KB 完整代码如下: // Problem#:

20180610模拟赛T1——脱离地牢

Description 在一个神秘的国度里,年轻的王子Paris与美丽的公主Helen在一起过着幸福的生活.他们都随身带有一块带磁性的阴阳魔法石,身居地狱的魔王Satan早就想着得到这两块石头了,只要把它们溶化,Satan就能吸收其精华大增自己的魔力.于是有一天他趁二人不留意,把他们带到了自己的地牢,分别困在了不同的地方.然后Satan念起了咒语,准备炼狱,界时二人都将葬身于这地牢里. 危险!Paris与Helen都知道了Satan的意图,他们要怎样才能打败魔王,脱离地牢呢?Paris想起了父王

编程题目分类(剪辑)

1. 编程入门 2. 数据结构 3. 字符串 4. 排序 5. 图遍历 6. 图算法 7. 搜索:剪枝,启发式搜索 8. 动态规划/递推 9. 分治/递归 10. 贪心 11. 模拟 12. 算术与代数 13. 组合问题 14. 数论 15. 网格,几何,计算几何 [编程入门] PC 110101, uva 100, The 3n+1 problem, 难度 1 PC 110102, uva 10189, Minesweeper, 难度 1 PC 110103, uva 10137, The T

(转)sicily题目分类

Sicily题目分类 ·         [数据结构/图论] 1310 Right-Heavy Tree   笛卡尔树相关,复杂度O(N)或O(NlogN). ·1426 Phone List         电话号码前缀检索,trie树相关. ·1443 Printer Queue      基本队列操作. ·1149 等价表达式         判断表达式是否等价(递归求解) ·1136 山海经             n长序列里求m次区间询问的最大连续子区间和.线段树/RMQ ·1252

POJ 2251 Dungeon Master(地牢大师)

p.MsoNormal { margin-bottom: 10.0000pt; font-family: Tahoma; font-size: 11.0000pt } h1 { margin-top: 5.0000pt; margin-bottom: 5.0000pt; text-align: left; font-family: 宋体; font-weight: bold; font-size: 24.0000pt } span.10 { font-family: "Times New Rom

CSS的三种手段让元素脱离标准本文档流

1.浮动 浮动是CSS中用到的最多的一个选项,他有三个性质.关于浮动我们要强调一点,永远不是一个东西单独浮动,浮动都是一起浮动,要浮动,大家都浮动. 1.1 浮动元素脱离标准文档流 1.1.1 大概描述:有两个盒子,一个盒子浮动,一个盒子不浮动.浮动的盒子会脱离标准文档流,不浮动的盒子会在标准文档流中成为第一个,所以两者出现覆盖现象. 1.1.2 大概描述:一个行内标签在标准文档流中是不能设置宽高的,但是使用float使其脱离文档流之后,就可以对其设置宽高了.所有浮动的标签不会去区分行内标签和块

position脱离文档流与浮动脱离文档流的区别

以前我觉得position:absolute;是可以脱离文档流的,float:left;也可以脱离文档流,就觉得二者是一样的,感觉可以去浮动的方法来解决position:absolute;引起的父元素塌陷问题,结果证明我错了...下边是一个demo. 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 &l

1215 迷宫

1215 迷宫 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在N*N的迷宫内,“#”为墙,“.”为路,“s”为起点,“e”为终点,一共4个方向可以走.从左上角((0,0)“s”)位置处走到右下角((n-1,n-1)“e”)位置处,可以走通则输出YES,不可以走则输出NO. 输入描述 Input Description 输入的第一行为一个整数m,表示迷宫的数量. 其后每个迷宫数据的第一行为一个整数n(n≤16),表示迷宫的边长

codecombat之边远地区的森林23-30关及地牢40\41关代码分享

codecombat中国游戏网址: http://www.codecombat.cn/ 所有代码为javascript代码分享 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23.Agrippa防守 loop { var enemy = this.findNearestEnemy(); if(enemy) { // 用 distanceTo 获取与敌人的距离. var distance = this.distanceTo(enemy); // 如果距离小于5米...