欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

HDOJ1728 逃离迷宫 ---- DFS+剪枝

程序员文章站 2022-05-20 21:35:10
...

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1728

Problem Description

  给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是,gloria是个没什么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时,gloria所面向的方向未定,她可以选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗?

 

 

Input

  第1行为一个整数t (1 ≤ t ≤ 100),表示测试数据的个数,接下来为t组测试数据,每组测试数据中,
  第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符'.'表示该位置为空地,字符'*'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x1, y1, x2, y2 (1 ≤ k ≤ 10, 1 ≤ x1, x2 ≤ n, 1 ≤ y1, y2 ≤ m),其中k表示gloria最多能转的弯数,(x1, y1), (x2, y2)表示两个位置,其中x1,x2对应列,y1, y2对应行。

 

 

Output

  每组测试数据对应为一行,若gloria能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。

 

 

Sample Input

 

2 5 5 ...** *.**. ..... ..... *.... 1 1 1 1 3 5 5 ...** *.**. ..... ..... *.... 2 1 1 1 3

 

 

Sample Output

 

no yes

 

 题解:可以用DFS搜索所有情况判断是否有满足题目条件的。定义一个结构体Node,成员变量有x,y表示行列坐标,dir表示方向,count表示转弯次数。bool dfs(Node node)就表示满足的node节点能否走到终点。

从起点开始判断,只需要四次循环,走上下左右四个方向,任何一个方向dfs返回true就说明可以走到终点,否则不能。

每次dfs一个节点时,需要先判断是否是墙,是否越界,转弯次数是否超标。最重要的是需要剪枝,如果dfs到某个node时,之前可能已经搜过该node了,就需要判断是否需要剪枝,如果判断出之前搜过该点,并且之前搜该店时最小的转弯次数比本次搜该点的转弯次数小(有点绕),那么现在去搜这个点肯定肯定走不到终点,所以需要直接return false来剪枝,没有这步剪枝应该会TLE。

 为了容易看明白些,代码有些可以省略简写的地方没有省略,比如搜4个方向可以for循环,这里就直接贴了4遍代码。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define TOP 0
#define BOTTOM 1
#define LEFT 2
#define RIGHT 3
using namespace std;
int m,n;   // 地图行列数
int Max;    // 最多转弯次数
char Map[105][105]; // 存放地图,从1开始
// 避免走回头路,要满足该点visited且转弯次数更大
bool visited[105][105];     //每个点访问记录
int visitedCount[105][105];     // 记录每个点访问时的转弯次数
struct Node {
    int x,y;        // 位置,x:行,y:列
    int dir;        // 方向
    int count;      // 转弯次数
    Node() {
        dir = count = x = y = 0;
    }
}start,End;             // 起始点和目标点

/**
 * 深度优先搜索
 */
bool dfs(Node node) {
    int x = node.x; //行
    int y = node.y; //列
    if (Map[x][y] == '*')
        return false;
    if (visited[x][y]) {
        if (visitedCount[x][y] < node.count) {
            // 走了回头路且肯定会失败
            return false;    
        } else {
            // 更新转弯次数
            visitedCount[x][y] = node.count;
        }
        
    }
    if (x < 1 || y < 1 || x > m || y > n) {
        //越界
        return false;
    }
    if (node.count > Max) {
        // 转弯次数超出限制
        return false;
    }
    if (x == End.x && y == End.y) {
        // 达到终点
        return true;
    }
    /*
     * 该点可以走
     */
    visited[x][y] = true;
    visitedCount[x][y] = node.count;
    Node temp;
    // 走四个方向
    // 上
    temp.x = x - 1,temp.y = y,temp.dir = TOP;
    temp.count = (node.dir == TOP ? node.count : node.count+1);
    // 起点特判
    if (node.x == start.x && node.y == start.y)
        temp.count = 0;
    if (dfs(temp) == true)
        return true;
    // 下
    temp.x = x + 1,temp.y = y,temp.dir = BOTTOM;
    temp.count = (node.dir == BOTTOM ? node.count : node.count+1);
    if (node.x == start.x && node.y == start.y)
        temp.count = 0;
    if (dfs(temp) == true)
        return true;
    // 左
    temp.x = x,temp.y = y - 1,temp.dir = LEFT;
    temp.count = (node.dir == LEFT ? node.count : node.count+1);
    if (node.x == start.x && node.y == start.y)
        temp.count = 0;
    if (dfs(temp) == true)
        return true;
    // 右
    temp.x = x,temp.y = y + 1,temp.dir = RIGHT;
    temp.count = (node.dir == RIGHT ? node.count : node.count+1);
    if (node.x == start.x && node.y == start.y)
        temp.count = 0;
    if (dfs(temp) == true)
        return true;
        
    return false;    
}


int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        memset(visitedCount,0,sizeof(visitedCount));
        memset(visited,0,sizeof(visited));
        scanf("%d%d",&m,&n);
        for (int i = 1;i <= m;i++)
            scanf("%s",Map[i] + 1);
        scanf("%d",&Max);
        scanf("%d%d%d%d",&start.y,&start.x,&End.y,&End.x);
        start.count = 0;
        if (dfs(start)) {
            printf("yes\n");
        } else {
            printf("no\n");
        }
    }
    
    return 0;
}

 

相关标签: dfs 迷宫问题