HDU 1010 Tempter of the Bone

题目链接:HDU 1010

Description

暑假的时候,小明和朋友去迷宫中寻宝。然而,当他拿到宝贝时,迷宫开始剧烈震动,他感到地面正在下沉,他们意识到这是一个陷阱!他们想尽一切办法逃出去。
迷宫是一个大小为 N*M 的长方形,迷宫中有一扇门。一开始,门是关着的,他会在第 t 秒的时间打开。因为,小明和朋友必须在第 t 秒到大门口。每一秒,他都可以向上下左右四个方向移动一个点。一旦他移动了,他刚才所在的点就消失,(这意味着他不能回到他已经走过的点)。他不能在一个点上停留超过一秒,并且不能走障碍点。小明和朋友能安全的逃出吗?

Input

输入由多个测试用例组成。每个测试用例的第一行包含三个整数 N、M 和 T ( 1 < N , M < 7 ; 0 < T < 50 ),分别表示迷宫的大小和门打开的时间。接下来的N行给出迷宫布局,每一行包含M个字符。下列字母分别表示:

"X": 一堵墙,小明和朋友不能在上面停留
"S": 起点
"D": 门
".": 可以走的点

输入以 3 个 0 时结束。这个测试用例不需要处理。

Output

对于每组样例输出一行。
如果小明能够安全逃出,输出 "YES" ,否则输出 "NO"。

Sample Input

4 4 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D
0 0 0

Sample Output

NO
YES

题意

给定一个迷宫,每个格子只能走一次,走过就会消失,门打开的时间是给定的,只打开1s,问是否能够逃离迷宫。

题解:

刚开始以为这是一道变形的bfs迷宫题,还是自己太菜了,orz,其实这是一道dfs的题(不知道bfs能不能解出来,但是dfs的比较简单),

大佬们总是能在bfs和dfs之间随意切换怎么做都能做的出来~

我最后是用bfs做的。
根据题意,迷宫的门只在第t s的时候开1s,所以可以用dfs跑,把所有能到达门的所有路线都走一遍,然后判断当前是不是第t s。当然如果只是这样直接用dfs做的话,绝对会T,而且超时超的不是一点半点,dfs会耗费大量的运算在已经无法到达终点的道路上越走越远,比如在没到达门之前,时间就到了t s,那还能走到终点吗?

本题的难点在于dfs的剪枝

奇偶剪枝是本题剪枝中的关键,在数学这块儿我也不是很懂,在看了大佬们的博客讲解后,奇偶剪枝是基于这样的一个事实:两个点之间的最短路径和他们之间的任一距离同奇偶(按格子走时),在dfs时,算出当前剩余时间(t-当前走的时间)和当前点与目标点之间的曼哈顿距离(横纵坐标差值之和)的差值,如果这个数是偶数,说明两者同奇偶,否则奇偶不同。
还有就是在输入迷宫后,判断时间是不是大于可走的格子数量,如果是的话,显然没走到门就已经没格子可以走了(格子踩过就会消失)。

代码

#include<iostream>
#include<cmath>
#include<string.h>
using namespace std;

typedef long long ll;
int n, m, cc;
char feld[9][9];
int gx, gy, sx, sy;
int OK = 0;
int dir[4][2] = { 1,0,0,1,-1,0,0,-1 };
void dfs(int x, int y, int t) {
    if (x < 0 || x >= n || y < 0 || y >= m)
        return;
    if (x == gx && y == gy && cc == t) {
        OK = 1;
        return;
    }
    if (OK)
        return;
    int temp = cc - t - abs(gx - x) - abs(gy - y);
    if (temp < 0 || temp & 1)
    {
        return;
    }
    int nx, ny;
    for (int i(0); i < 4; i++) {
        nx = x + dir[i][0];
        ny = y + dir[i][1];
        if (nx < 0 || nx >= n || ny < 0 || ny >= m)
            continue;
        if (feld[nx][ny] != 'X') {
            feld[nx][ny] = 'X';
            dfs(nx, ny, t + 1);
            feld[nx][ny] = '.';
        }
    }
}
int main() {
    while (cin >> n >> m >> cc, n) {
        memset(feld, 0, sizeof(feld));
        int Wall = 0;
        for (int i(0); i < n; i++)
            cin >> feld[i];
        for (int i(0); i < n; i++)
            for (int j(0); j < m; j++)
                if (feld[i][j] == 'S') {
                    sx = i; sy = j;
                }
                else if (feld[i][j] == 'D') {
                    gx = i; gy = j;
                }
                else if (feld[i][j] == 'X')
                    Wall++;
        if (n*m - Wall <cc)
        {
            cout << "NO" << endl;
            continue;
        }
        OK = 0;
        feld[sx][sy] = 'X';
        dfs(sx, sy, 0);
        if (OK)
            cout << "YES" << endl;
        else cout << "NO" << endl;
    }
    return 0;
}
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
正在热议
更多
# 一张图晒出你司的标语 #
4341次浏览 75人参与
# AI面会问哪些问题? #
28026次浏览 559人参与
# 开放七大实习专项,百度暑期实习值得冲吗 #
15273次浏览 221人参与
# 你的实习产出是真实的还是包装的? #
20248次浏览 342人参与
# 找AI工作可以去哪些公司? #
9210次浏览 239人参与
# 春招至今,你的战绩如何? #
65577次浏览 583人参与
# 米连集团26产品管培生项目 #
13373次浏览 285人参与
# 从事AI岗需要掌握哪些技术栈? #
9043次浏览 311人参与
# 中国电信笔试 #
32021次浏览 292人参与
# 你做过最难的笔试是哪家公司 #
33775次浏览 238人参与
# 投递几十家公司,到现在0offer,大家都一样吗 #
340878次浏览 2175人参与
# 哪些公司真双非友好? #
69630次浏览 289人参与
# 阿里笔试 #
178680次浏览 1317人参与
# 机械人避雷的岗位/公司 #
62704次浏览 393人参与
# 小马智行求职进展汇总 #
25133次浏览 80人参与
# 第一份工作一定要去大厂吗 #
14734次浏览 122人参与
# 金三银四,你的春招进行到哪个阶段了? #
22098次浏览 280人参与
# 为了减少AI幻觉,你注入过哪些设定? #
26263次浏览 310人参与
# 应届生第一份工资要多少合适 #
20691次浏览 86人参与
# 沪漂/北漂你觉得哪个更苦? #
9939次浏览 193人参与
# 聊聊你的职场新体验 #
336515次浏览 1895人参与
# HR最不可信的一句话是__ #
6306次浏览 114人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务