问题描述
曾经的我不过是一介草民,混迹市井,默默无名。直到我被罗马的士兵从家乡捉走丢进竞技场……
对手出现了,我架紧盾牌想要防御,只觉得巨大的冲击力有如一面城墙冲涌而来,击碎了我的盾牌,我两眼发昏,沉重的身躯轰然倒地。
——我好想逃。
但罗马最大的竞技场,哪有这么容易逃得掉。工程师们早就在地上装了传送机关,虽不会伤人,却会将站在上面的人传到它指向的位置。若是几个传送机关围成一个环,不小心踩在上面的人就会被一圈圈地反复传送……想到这里,我不由得打了个寒颤。必须避开这些危险的地方!
在一个 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;
}