A计划 HDU 2102

题目背景
可怜的公主在一次次被魔王掳走一次次被骑士们救回来之后,而今,不幸的她再一次面临生命的考验。魔王已经发出消息说将在T时刻吃掉公主,因为他听信谣言说吃公主的肉也能长生不老。年迈的国王正是心急如焚,告招天下勇士来拯救公主。不过公主早已习以为常,她深信智勇的骑士LJ肯定能将她救出。
现据密探所报,公主被关在一个两层的迷宫里,迷宫的入口是S(0,0,0),公主的位置用P表示,时空传输机用#表示,墙用*表示,平地用.表示。骑士们一进入时空传输机就会被转到另一层的相对位置,但如果被转到的位置是墙的话,那骑士们就会被撞死。骑士们在一层中只能前后左右移动,每移动一格花1时刻。层间的移动只能通过时空传输机,且不需要任何时间。
Input
输入的第一行C表示共有C个测试数据,每个测试数据的前一行有三个整数N,M,T。 N,M迷宫的大小N*M(1 <= N,M <=10)。T如上所意。接下去的前N*M表示迷宫的第一层的布置情况,后N*M表示迷宫第二层的布置情况。
Output
如果骑士们能够在T时刻能找到公主就输出“YES”,否则输出“NO”。
Sample Input

1
5 5 14
S*#*.
.#...
.....
****.
...#.

..*.P
#.*..
***..
...*.
*.#..

Sample Output
YES

题目大意:。。。字数不多的中文题。还是说一下吧,给你一个三维地图。地图大小:2*n*m。S是出发坐标,不过题目直接说了是(0,0,0),不用跑一边地图找。*是墙,不能走。P是要到达的公主位置。#是时空穿梭机,可以从当前层的位置到另一层正对的位置。比如(0,1,1)–>(1,1,1)、(1,2,2)–>(2,2,2)。我不确定#是不是只在第0层,所以直接按照#可能两层都可能有做的。

注意:从一层到另一层的时间不算。如果传送的对面是墙,则传送过去勇士(骑士)会GG。从S—>P,步数(时间)要在输入时间 T 的范围内,不然公主就GG了。

Think: BFS广度优先搜索,这题是三维的地图,不过只有两层,不算难,注意层与层之间的跳转的判断就好。

C++代码如下:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
typedef struct node
{
    int a;  //横坐标
    int b;  //纵坐标
    int c;  //第几次层
    int step;  //步数(时间)
} node;
node p[1010];  //题目n、m都比较小,不用开太大
bool b[2][15][15];  //布尔类型,用于标记地图上的点是否走过
int h[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};  //跑四个方向的数组
//之前都是用next数组表示,没毛病
//不知道为啥这个名字就报错了,就改名为数组名h了。。。
char s[2][15][15];  //地图
int n, m, k;  //地图的行、列。时间
void BFS();  //广搜
int main()
{
    int t;
    scanf("%d", &t);  //习惯t为输入的组数
    while(t--)
    {
        scanf("%d %d %d", &n, &m, &k);  //k为截至时间
        int i;
        for(i = 0; i < n; i++)
        {
            scanf("%s", s[0][i]);
        }
        for(i = 0; i < n; i++)
        {
            scanf("%s", s[1][i]);
        }
        BFS();  //广搜
    }
    return 0;
}
void BFS()
{
    memset(b, 0, sizeof(b));  //初始都没走过任何位置
    int i;
    int head = 1;
    int top = 1;
    p[head].a = 0;
    p[head].b = 0;
    p[head].c = 0;
    p[head].step = 0;
    b[0][0][0] = 1;  //标记走过
    top++;
    int aa, bb, cc;
    while(head < top)
    {
        node t = p[head];
        if(t.step >= k)  //公主会GG,来不及了
        {
            printf("NO\n");
            return ;
        }
        head++;
        for(i = 0; i < 4; i++)
        {
            aa = t.a + h[i][0];
            bb = t.b + h[i][1];
            cc = t.c;
            if(aa < 0||aa >= n||bb < 0||bb >= m)
            {
                continue;  //超出边界的位置不能入队
            }
            if(cc == 0)  //当前是0层
            {
                if(b[0][aa][bb] == 1||s[0][aa][bb] == '*')
                {
                    continue;  //如果走过了,或者是墙,则止步
                }
                b[0][aa][bb] = 1;  //标记已经走过这个位置
                if(s[0][aa][bb] == '.')  //入队
                {
                    p[top].a = aa;
                    p[top].b = bb;
                    p[top].c = 0;
                    p[top].step = t.step + 1;
                    top++;
                }
                else if(s[0][aa][bb] == '#')  //遇到传送机
                {                             //下面没判断是否为墙*,因为会GG,不需要处理
                    if(s[1][aa][bb] == 'P')  //对面是公主,欢天喜地
                    {
                        printf("YES\n");
                        return ;
                    }
                    else if(s[1][aa][bb] == '.')  //入队
                    {
                        b[1][aa][bb] = 1;  //不可少!!!
                        p[top].a = aa;
                        p[top].b = bb;
                        p[top].c = 1;
                        p[top].step = t.step + 1;
                        top++;
                    }
                }
                else if(s[0][aa][bb] == 'P')  //成功到达公主所在地
                {
                    printf("YES\n");
                    return ;
                }
            }
            else  //当前是第一层,道理同上
            {
                if(b[1][aa][bb]||s[1][aa][bb] == '*')
                {
                    continue;
                }
                b[1][aa][bb] = 1;
                if(s[1][aa][bb] == '.')
                {
                    p[top].a = aa;
                    p[top].b = bb;
                    p[top].c = 1;
                    p[top].step = t.step + 1;
                    top++;
                }
                else if(s[1][aa][bb] == '#')
                {
                    if(s[0][aa][bb] == 'P')
                    {
                        printf("YES\n");
                        return ;
                    }
                    else if(s[0][aa][bb] == '.')
                    {
                        b[0][aa][bb] = 1;  //不可少!!!
                        p[top].a = aa;
                        p[top].b = bb;
                        p[top].c = 0;
                        p[top].step = t.step + 1;
                        top++;
                    }
                }
                else if(s[1][aa][bb] == 'P')
                {
                    printf("YES\n");
                    return ;
                }
            }
        }
    }
    printf("NO\n");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值