T245982 「KDOI-01」醉花阴

「KDOI-01」醉花阴

题目背景

最近,kdy迷上了一款游戏。在游戏里,他扮演着一只逍遥自在的大白鹅。

现在,他正在控制着大白鹅完成最终的任务。

 题目描述

大白鹅现在位于一个 n*m  的迷宫中,迷宫由数字 0 和 1 组成,若某一格上的数为 0,则表示该处可以通行,若为 1,则表示该处不可通行。刚开始,它位于 (a,b) 的位置,而出口在 (c,d)。矩阵左上角坐标是 (1,1),右下角坐标是 (n,m)。

不巧的是,这个迷宫里有 k 个猎手,他们会对大白鹅造成威胁。当两者坐标相同时,大白鹅就会被抓住,无论是在入口还是出口。

猎手和大白鹅每秒都能移动一个单位,当然他们也可以不移动。两者同时开始移动且他们都只能向上下左右四个方向移动。现在他想知道,大白鹅有没有可能在不被猎手抓到的情况下走出迷宫,我们假设这些猎手都足够聪明。

kdy 想让你帮他算算,大白鹅能不能逃出迷宫。因为 kdyl 还要玩二周目,所以他只给了你 500ms 的时间。

 输入格式

本题有多组数据,第一行一个正整数 t,为数据组数。接下来 t 组数据,其中对于每一组数据:

第一行两个正整数 n  和 m。

接下来输入一个 n 行 m 列的矩阵,矩阵只会由 0 和 1 组成。

紧接着是一个整数 k,表示猎手数目。

接下来 k 行,每行两个正整数,表示 k 个猎手的初始坐标。

最后一行四个整数 a,b,c,d,表示入口和出口的坐标。

本题涉及的所有坐标都在地图内且不会位于障碍处。

 输出格式

对于每一组数据,如果大白鹅可以成功走出迷宫且不被抓到,输出 'T',否则输出 'F'。

 样例 1

样例输入 1
2
3 4
0100
0011
1001
2
1 1
1 4
2 2 3 2
2 2
01
10
0
1 1 2 2

样例输出 1
T
F

 提示

样例解释:

对于第一组数据,画出示意图如下:

大白鹅明显不会被追上。

对于第二组数据,大白鹅不可能到达终点。

本题采用捆绑数据测试。

 - Subtask 0(10 pts):k=0。
 - Subtask 1(10 pts):n,m<=10。
 - Subtask 2(30 pts):k<=10^2。
 - Subtask 3(50 pts):无特殊限制。
 
对于全部数据,n,m<=10^3,k<=n*m,t<=10。

首先如果存在一条路能让大白鹅到终点(先不考虑猎人),我们在考虑猎人。

否则不存在一条路能让大白鹅到终点直接输出‘F’就行。

因为用的bfs搜索,我们一步一步找到大白鹅到终点的路径,如果猎人的路径大于大白鹅到终点的路径,就追不上大白鹅。(我们可以假设这样的模型,大白鹅和猎人在一条笔直的赛道上赛跑,他们速度相等,就看谁离终点进,谁就获胜,你可以在草稿纸上画出示意图)

那么接下来就是套bfs的模板了,不了解bfs的可以看我之前的博客*/

下面上代码

#include <iostream>
#include <string>
#include <queue>
#include <cstring>
using namespace std;
int max_step1 = 0;
int temp_step1 = 0;
int n, m;
bool vis[1000][1000];
string maze[1000];
int hunterx[1000000];
int huntery[1000000];
int dir[4][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};             /*方向*/
int start_x, start_y, end_x, end_y;
struct node                                                    /*结构体*/
{
    int x, y, step;
    node(int _x, int _y, int _step)
    {
        x = _x;
        y = _y;
        step = _step;
    }
};
void speed()                                                   /*使cin具有scanf一样的速度*/
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
}
bool in(int x, int y)                                         /*是否越界*/
{
    return x >= 0 && x < n && y >= 0 && y < m;
}
bool bfs1(int x, int y)                                      /*广度搜索*/
{
    queue<node> q;
    q.push(node(x, y, 0));
    vis[x][y] = 1;
    while (!q.empty())
    {
        node temp = q.front();
        q.pop();
        for (int i = 0; i < 4; i++)
        {
            int tx = temp.x + dir[i][0];
            int ty = temp.y + dir[i][1];
            if (in(tx, ty))
            {
                if (maze[tx][ty] != '1' && !vis[tx][ty])
                {
                    if (tx == end_x && ty == end_y)
                    {
                        max_step1 = temp.step + 1;         /*如果能到终点就把到终点的步数拿出来*/
                        return true;
                    }
                    else
                    {
                        vis[tx][ty] = 1;
                        q.push(node(tx, ty, temp.step + 1));
                    }
                }
            }
        }
    }
    return false;
}
bool bfs2(int x, int y)
{
    queue<node> q;
    q.push(node(x, y, 0));
    vis[x][y] = 1;
    if (x == start_x && y == start_y)                      /*防止特例*/
    {
        return true;
    }
    while (!q.empty())
    {
        node temp = q.front();
        q.pop();
        for (int i = 0; i < 4; i++)
        {
            int tx = temp.x + dir[i][0];
            int ty = temp.y + dir[i][1];
            if (in(tx, ty))
            {
                if (maze[tx][ty] != '1' && !vis[tx][ty])
                {
                    if (tx == end_x && ty == end_y)
                    {
                        temp_step1 = temp.step + 1;     /*猎人到终点的距离*/
                        return true;
                    }
                    else
                    {
                        vis[tx][ty] = 1;
                        q.push(node(tx, ty, temp.step + 1));
                        if (temp.step + 1 > max_step1)  /*剪枝*/
                        {
                            return false;
                        }
                    }
                }
            }
        }
    }
    return false;
}
int main()
{
    speed();
    int t;
    cin >> t;
    while (t > 0)
    {
        cin >> n >> m;
        bool flag = true;
        memset(vis, 0, sizeof(vis));
        max_step1 = 0;
        for (int i = 0; i < n; i++)
        {
            cin >> maze[i];
        }
        int k;
        cin >> k;
        for (int i = 0; i < k; i++)
        {
            cin >> hunterx[i] >> huntery[i];
            hunterx[i]--;
            huntery[i]--;
        }
        cin >> start_x >> start_y >> end_x >> end_y;
        start_x--;
        start_y--;
        end_x--;
        end_y--;
        if (start_x == end_x && start_y == end_y)
        {
            cout << 'T' << endl;
        }
        else
        {
            if (bfs1(start_x, start_y) == false)                     /*如果大白鹅到不了终点*/
            {
                cout << 'F' << endl;
            }
            else
            {
                for (int i = 0; i < k; i++)
                {
                    memset(vis, 0, sizeof(vis));
                    temp_step1 = 0;
                    if (bfs2(hunterx[i], huntery[i]) == true && temp_step1 <= max_step1)     /*如果猎人比大白鹅到的更快*/
                    {
                        flag = false;
                        cout << 'F' << endl;
                        break;
                    }
                }
                if (flag == true)
                {
                    cout << 'T' << endl;
                }
            }
        }
        t--;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值