广搜 迷宫(zznu 1962)

http://acm.zznu.edu.cn/problem.php?id=1962

题目描述

在很多 RPG (Role-playing Games) 游戏中,迷宫往往是非常复杂的游戏环节。通常来说,我们在走迷宫的时候都需要花非常多的时间来尝试不同的路径。但如果有了算法和计算机的帮助,我们能不能有更快的方式来解决这个问题?我们可以进行一些尝试。

现在我们有一个 N 行 M 列的迷宫。迷宫的每个格子如果是空地则可以站人,如果是障碍则不行。在一个格子上,我们可以一步移动到它相邻的 8 个空地上,但不能离开地图的边界或者跨过两个障碍的夹缝。下图是一个移动规则的示例。

为了离开迷宫,我们还需要触发迷宫中所有的机关。迷宫里总共有 K 个机关,每个机关都落在一个不同的空地上。如果我们到达了某个机关所在的格子时,这个机关就会被自动触发,并在触发之后立即消失。我们的目标是按顺序触发所有的 K             个机关,而当最后一个机关被触发时,我们就可以离开迷宫了。

现在我们已经拿到了迷宫地图,并且知道所有障碍、机关的位置。初始时我们位于迷宫的某个非障碍格子上,请你计算我们最少需要移动多少步才能离开迷宫?

输入

输入的第一行是测试数据的组数 T (T ≤ 20)。

对于每组测试数据:第一行包含地图的行数 N (2 ≤ N  ≤ 100),列数 M(2 ≤ M  ≤ 100) 和机关的数量 K(1 ≤ K ≤10)。接下来 N 行,每行包含 M 个字符,其中字符 ‘#’ 表示障碍,而 ‘.’ 表示空地。接下来一行描述了我们的初始位置 (x, y),表示我们一开始在第 x 行第 y 列的格子上。这个格子保证是个空地。接下来 K 行,每行给出了一个机关的位置。所有的机关都不会出现在障碍上,并且任意两个机关不会出现在同一个空地上。我们需要按输入给定的顺序触发所有的 K 个机关。

输出

对于每组测试数据,输出离开迷宫所需要的最少步数。如果无论如何都不能离开迷宫,输出 -1。

样例输入

3
3 3 2
...
...
...
1 1
1 3
2 2
3 3 1
...
.#.
...
1 1
3 3
2 3 1
..#
.#.
1 1
2 3

样例输出

3
3
-1

提示

来源

2015轻院校赛

只需要注意起始点不能是机关, 但是如果只有一个点的话, 起始点是可以是机关的

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;

#define N 110
#define met(a, b) memset(a, b, sizeof(a))

using namespace std;

const int dir[8][2] = {{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1,},{1,0},{1,1}};

struct node
{
    int x, y, step;
}JG[N];

int n, m, k, vis[N][N];
char G[N][N];

bool Judge(int x, int y)
{
    if(x>=1 && x<=n && y>=1 && y<=m && !vis[x][y] && (G[x][y]==‘.‘ || G[x][y]==‘@‘))
        return 1;
    return 0;
}

int BFS(int w)
{
    node p, q;
    p = JG[w];
    p.step = 0;

    queue<node>Q;
    Q.push(p);

    memset(vis, 0, sizeof(vis));
    vis[p.x][p.y] = 1;
    G[JG[w+1].x][JG[w+1].y] = ‘@‘;

    while(Q.size())
    {
        p = Q.front(); Q.pop();

        if(G[p.x][p.y]==‘@‘)
        {
            G[p.x][p.y] = ‘.‘;
            return p.step;
        }

        for(int i=0; i<8; i++)
        {
            q.x = p.x + dir[i][0];
            q.y = p.y + dir[i][1];
            q.step = p.step + 1;

            if(i==1 || i==3 || i==4 || i==6)
            {
                if(Judge(q.x, q.y))
                {
                    vis[q.x][q.y] = 1;
                    Q.push(q);
                }
            }
            else if(i==0)
            {
                if(Judge(q.x, q.y))
                {
                    if(G[p.x-1][p.y]==‘#‘ && G[p.x][p.y-1]==‘#‘) continue;
                    vis[q.x][q.y] = 1;
                    Q.push(q);
                }
            }
            else if(i==2)
            {
                if(Judge(q.x, q.y))
                {
                    if(G[p.x-1][p.y]==‘#‘ && G[p.x][p.y+1]==‘#‘) continue;
                    vis[q.x][q.y] = 1;
                    Q.push(q);
                }
            }
            else if(i==5)
            {
                if(Judge(q.x, q.y))
                {
                    if(G[p.x+1][p.y]==‘#‘ && G[p.x][p.y-1]==‘#‘) continue;
                    vis[q.x][q.y] = 1;
                    Q.push(q);
                }
            }
            else ///if(i==7)
            {
                if(Judge(q.x, q.y))
                {
                    if(G[p.x+1][p.y]==‘#‘ && G[p.x][p.y+1]==‘#‘) continue;
                    vis[q.x][q.y] = 1;
                    Q.push(q);
                }
            }

        }
    }
    return -1;
}

int main ()
{
    int t;

    scanf("%d", &t);

    while(t--)
    {
        int i, ans, sum=0;

        scanf("%d%d%d", &n, &m, &k);

        memset(G, 0, sizeof(G));

        for(i=1; i<=n; i++)
            scanf("%s", G[i]+1);

        scanf("%d%d", &JG[0].x, &JG[0].y);
        for(i=1; i<=k; i++)
        {
            scanf("%d%d", &JG[i].x, &JG[i].y);
            G[JG[i].x][JG[i].y] = ‘*‘;
        }

        if(G[JG[0].x][JG[0].y]==‘*‘ && k!=1)
        {
            printf("-1\n");
            continue;
        }

        for(i=0; i<k; i++) ///第i次查找
        {
            ans = BFS(i);
            if(ans==-1) break;
            sum += ans;
        }

        if(ans==-1) printf("-1\n");
        else        printf("%d\n", sum);
    }
    return 0;
}
时间: 2025-01-02 01:05:12

广搜 迷宫(zznu 1962)的相关文章

POJ 3984 迷宫问题 广搜迷宫解法

Description 定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线. Input 一个5 × 5的二维数组,表示一个迷宫.数据保证有唯一解. Output 左上角到右下角的最短路径,格式如样例所示. Sa

迷宫广搜

上学期学了C,这学期学C++.感觉最难的还是算法,上周作业的一道广搜题是我第一次接触广搜,由于第一学期刚学编程就接触的太多的算法难题,不禁对代码产生畏惧,不过还好没有放弃,虽然算法很难,但我慢慢找到了一点学数学时的乐趣.先介绍一下这道未来的我看过来会觉得很简单一道题吧 You are provided a maze(迷宫), and you need to program to find the least steps to walk from the start to the end.And

poj 3984:迷宫问题(广搜,入门题)

迷宫问题 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7635   Accepted: 4474 Description 定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要

迷宫问题(深搜 广搜)

题目描述: 给出一个m*n的迷宫图和一个入口,一个出口. 编一个程序,打印一条从迷宫入口到出口的路径. -1表示走不通,0表示能走,只能上下左右走: 无路可走输出"no way": 样例输入: 8 5-1 -1 -1 -1 -1 0 0 0 0 -1-1 -1 -1 0 -1-1 0 0 0 -1-1 0 0 1 -1-1 0 0 0 -1-1 -1 -1 0 -1-1 0 0 0 -12 18 4 8 5-1 -1 -1 -1 -10 0 0 0 -1-1 -1 -1 0 -1-1

HDU 1026 Ignatius and the Princess I 迷宫广搜剪枝问题

本题是个经典的迷宫广搜问题类型了.网上看到好多解法. 很多解题报告都没什么分析,更不会指出其中的关键点.代码更加像一大抄.有人分析也一大篇分析,不过全部都不切中关键,甚至在分析什么广搜和深搜区别,广搜为什么快之类的,还有喊什么暴搜之类的,全错了.估计这些代码都是抄过的. 通过一大段的时间研究,终于搞通了. 本题虽然可以说是广搜,但是其中的关键却是剪枝法,为什么呢? 因为迷宫并不能简单地广搜就能搜索出所有路径的,甚至只要迷宫大点就不能搜索出是否有路径,如果没有条件剪枝的情况下:不信,你严格写一个广

HDU 1240 (简单三维广搜) Asteroids!

给出一个三维的迷宫以及起点和终点,求能否到大终点,若果能输出最短步数 三维的问题无非就是变成了6个搜索方向 最后强调一下xyz的顺序,从输入数据来看,读入的顺序是map[z][x][y] 总之,这是很基础的一道题 1 //#define LOCAL 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <queue> 6 #include <algorithm

最短路问题------分别用深搜和广搜去解题

最少步数 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 这有一个迷宫,有0~8行和0~8列: 1,1,1,1,1,1,1,1,1 1,0,0,1,0,0,1,0,1 1,0,0,1,1,0,0,0,1 1,0,1,0,1,1,0,1,1 1,0,0,0,0,1,0,0,1 1,1,0,1,0,1,0,0,1 1,1,0,1,0,1,0,0,1 1,1,0,1,0,0,0,0,1 1,1,1,1,1,1,1,1,1 0表示道路,1表示墙. 现在输入一个道路的坐标作为起点

算法学习笔记 二叉树和图遍历—深搜 DFS 与广搜 BFS

图的深搜与广搜 马上又要秋招了,赶紧复习下基础知识.这里复习下二叉树.图的深搜与广搜.从图的遍历说起,图的遍历方法有两种:深度优先遍历(Depth First Search), 广度优先遍历(Breadth First Search),其经典应用走迷宫.N皇后.二叉树遍历等.遍历即按某种顺序访问"图"中所有的节点,顺序分为: 深度优先(优先往深处走),用的数据结构是栈, 主要是递归实现: 广度优先(优先走最近的),用的数据结构是队列,主要是迭代实现: 对于深搜,由于递归往往可以方便的利

POJ_2251(初识广搜)

Description You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed of unit cubes which may or may not be filled with rock. It takes one minute to move one unit north, south, east, west, up or down. You cannot m