28.我好想逃却逃不掉(深度优先+记录走过路径)【已解决】

问题描述

曾经的我不过是一介草民,混迹市井,默默无名。直到我被罗马的士兵从家乡捉走丢进竞技场……

对手出现了,我架紧盾牌想要防御,只觉得巨大的冲击力有如一面城墙冲涌而来,击碎了我的盾牌,我两眼发昏,沉重的身躯轰然倒地。

——我好想逃。

但罗马最大的竞技场,哪有这么容易逃得掉。工程师们早就在地上装了传送机关,虽不会伤人,却会将站在上面的人传到它指向的位置。若是几个传送机关围成一个环,不小心踩在上面的人就会被一圈圈地反复传送……想到这里,我不由得打了个寒颤。必须避开这些危险的地方!

在一个 N × M 的竞技场迷宫中,你的任务是找出在迷宫中,所有"危险位置"的数量。
"危险位置"定义为:如果站在该位置上,无论采取什么移动策略,都无法到达出口

竞技场中包含以下几种元素:

  • .:表示普通地板,可以自由移动到上下左右相邻的格子(不可以走斜线)
  • O:表示出口
  • U:表示向上的传送器,踩上去会被强制传送到上方的格子
  • D:表示向下的传送器,踩上去会被强制传送到下方的格子
  • L:表示向左的传送器,踩上去会被强制传送到左方的格子
  • R:表示向右的传送器,踩上去会被强制传送到右方的格子

注意,如果被传送出了竞技场之外,则算作死亡。

输入参数

  • N: 一个整数,表示竞技场地图的行数
  • M: 一个整数,表示竞技场地图的列数
  • data: 一个字符二维数组,表示竞技场地板地图。数组大小为 N × M,其中 1 ≤ N, M ≤ 100

测试样例

样例1:

输入:N = 5, M = 5, data = [ [".", ".", ".", ".", "."], [".", "R", "R", "D", "."], [".", "U", ".", "D", "R"], [".", "U", "L", "L", "."], [".", ".", ".", ".", "O"] ]
输出:10
解释:存在 10 个位置,如果站在这些位置上,将永远无法到达右下角的出口(用 X 标记):
['.', '.', '.', '.', '.']
['.', 'X', 'X', 'X', '.']
['.', 'X', 'X', 'X', 'X']
['.', 'X', 'X', 'X', '.']
['.', '.', '.', '.', 'O']

样例2:

输入:N = 4, M = 4, data = [[".", "R", ".", "O"], ["U", ".", "L", "."], [".", "D", ".", "."], [".", ".", "R", "D"]]
输出:2

样例3:

输入:N = 3, M = 3, data = [[".", "U", "O"], ["L", ".", "R"], ["D", ".", "."]]
输出:8

解题思路

深度优先判断所以入口的可行性,使用memo数组记录每次进去的路径,当再次踏入时说明是死循环返回false,当超出界限时返回false。遇到O说明遇到出口返回true。当有多种选择时取其的或集,当一种方式能出去说明该点不是必死点。

代码C++

#include <iostream>
#include <vector>


bool dfs(int N, int M, int i, int j, std::vector<std::vector<int>>& memo, const std::vector<std::vector<char>>& data){
    if(i >= N || j >=M || i < 0 || j < 0){
        return false;
    }//越界返回false
    if(memo[i][j] != -1){
        return false;
    }//来过了说明循环了
    memo[i][j] = 1;//标记来过
    bool temp = false;
    if(data[i][j] == 'O'){
        temp = true;
    }else if(data[i][j] == 'U'){
        temp = dfs(N,M,i-1,j,memo,data);
    }else if(data[i][j] == 'D'){
        temp = dfs(N,M,i+1,j,memo,data);
    }else if(data[i][j] == 'L'){
        temp = dfs(N,M,i,j-1,memo,data);
    }else if(data[i][j] == 'R'){
        temp = dfs(N,M,i,j+1,memo,data);
    }else{
        temp = dfs(N,M,i-1,j,memo,data) || dfs(N,M,i+1,j,memo,data) || dfs(N,M,i,j-1,memo,data)|| dfs(N,M,i,j+1,memo,data);
    }
    return temp;
}


int solution(int N, int M, std::vector<std::vector<char>> data) {
    // Edit your code here
    int ans = 0;
    for(int i = 0; i < N; i++){
        for(int j = 0;j < M; j++){
            std::vector<std::vector<int>> memo(N, std::vector<int>(M, -1));
            if(!dfs(N,M,i,j,memo,data)){
                ans++;
            }
        }
    }

    return ans;
}

int main() {
    // Add your test cases here
    std::vector<std::vector<char>> pattern = {
        {'.', '.', '.', '.', '.'},
{'.', 'R', 'R', 'D', '.'},
{'.', 'U', '.', 'D', 'R'},
{'.', 'U', 'L', 'L', '.'},
{'.', '.', '.', '.', 'O'}
    };

    std::cout << (solution(5, 5, pattern) == 10) << std::endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值