使用深度优先搜索(DFS)解决网格路径计数问题

源内容

在一个 7×7 的网格中,从左上角到左下角共有 88418 条路径。每条路径对应一个由 48 个字符组成的描述,包含字符 D(下)、U(上)、L(左)和 R(右)。现在给你一个路径描述,其中可能包含字符 ?(代表任意方向)。我们的任务是计算符合该描述的路径数量。

示例

> 输入: ??????R??????U??????????????????????????LD????D?

>

>

>

> 输出: 201

>

>

>

> 解释: 给定描述下有 201 条可能的路径。

使用深度优先搜索(DFS)的方法

> 核心思路是使用 DFS 算法。如果字符串中的当前字符是‘?’,我们就尝试所有四个方向;否则,我们就按照给定的方向(L, R, U, D)移动。

>

> 优化代码的剪枝/终止搜索策略

>

> 如果我们无法上下移动,但可以左右移动,或者无法左右移动,但可以上下移动,这种情况下网格会被分割成两部分。显然,我们无法访问到网格的所有部分,因此可以终止搜索。以下这四种情况也会导致部分网格未被访问,因此搜索也需要终止。

>

>

>

> – 如果右上对角线格子已访问,且上方和右方的格子未访问。

> – 如果右下对角线格子已访问,且下方和右方的格子未访问。

> – 如果左上对角线格子已访问,且上方和左方的格子未访问。

> – 如果左下对角线格子已访问,且下方和左方的格子未访问。

分步算法

  • 定义一个函数 INLINECODE370b1d47,它接受当前位置 INLINECODEc699f361 和路径描述字符串中的当前位置 pos 作为参数。
  • 基础情况 返回 1

– 如果字符串中的所有字符都已处理完毕,且当前位置是左下角格子,则返回 1(表示找到一条有效路径),否则返回 0。

  • 基础情况 返回 0(剪枝条件):

– 如果当前格子已经被访问过。

– 如果在处理完所有字符之前,已经到达了左下角(这意味着路径过短,无法填满网格)。

– 如果当前状态是:上下格子未访问,且左右格子已访问(形成横向阻断,无法继续填满网格)。

– 如果当前状态是:左右格子未访问,且上下格子已访问(形成纵向阻断,无法继续填满网格)。

– 如果当前状态是:右上对角线格子已访问,且上方和右方的格子未访问(形成死角,导致右上角区域无法被访问)。

– 如果当前状态是:右下对角线格子已访问,且下方和右方的格子未访问。

– 如果当前状态是:左上对角线格子已访问,且上方和左方的格子未访问。

– 如果当前状态是:左下对角线格子已访问,且下方和左方的格子未访问。

  • 将当前格子标记为已访问。
  • 初始化一个变量来存储路径数量。
  • 检查字符串中的当前字符是否为‘?’。如果是,尝试所有四个方向(递归调用)。
  • 检查字符串中的当前字符是否为方向指令(L, R, U, D)。如果是,向该方向移动。
  • 回溯:取消当前格子的访问标记(以便其他路径可以使用该格子)。
  • 返回路径的数量。

下面是这种方法的实现代码:

C++


// C++ 代码

#include

using namespace std;

// 用于检查坐标在网格中是否有效的宏

#define isValid(a) (a >= 0 && a < 7 ? 1 : 0)

// 方向常量

#define right 0

#define left 1

#define down 2

#define up 3

// 右、左、下、上的方向向量

int dx[4] = { 0, 0, 1, -1 };

int dy[4] = { 1, -1, 0, 0 };

// 路径描述字符串

string str;

int vis[7][7];

// 计算符合描述的路径数量的函数

int countPaths(int x, int y, int pos)

{

// 如果我们已经处理了字符串中的所有字符,

// 并且我们位于左下角,则返回 1

if (pos == (int)str.length())

return (x == 6 && y == 0);

// 如果在处理完所有字符之前到达了左下角,

// 则返回 0

if (x == 6 && y == 0)

return 0;

// 如果当前单元格已经被访问过,则返回 0

if (vis[x][y])

return 0;

// 数组用于跟踪相邻单元格的访问状态

vector visited(4, -1);

for (int k = 0; k < 4; k++)

if (isValid(x + dx[k]) && isValid(y + dy[k]))

visited[k] = vis[x + dx[k]][y + dy[k]];

// 如果我们处于上下方格未访问、

// 且左右方格已访问的位置,返回 0

if (!visited[down] && !visited[up] && visited[right]

&& visited[left])

return 0;

// 如果我们处于左右方格未访问、

// 且上下方格已访问的位置,返回 0

if (!visited[right] && !visited[left] && visited[down]

&& visited[up])

return 0;

// 如果我们处于一个位置 s

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/49452.html
点赞
0.00 平均评分 (0% 分数) - 0