it编程 > 软件设计 > 数据结构

数据结构学习 jz12字母迷宫

91人参与 2024-08-06 数据结构

dfs 回溯 剪枝

这个题和dfs有关,但是我之前没有接触过,我看了这一篇,看完之后写的答案。

我觉得很好的总结:

dfs模板

尝试每一种可能,一般都是用for循环。

在一些情况下,for循环这一步可以写到外面去,然后再调用dfs,比如这题就可以。,比如我刚刚提到的文章的油田问题。


题目:


我的思路:

其实就是模仿我刚刚提到的文章。

 我的dfs是:bool dfs(std::vector<std::vector<char>>& grid, std::string target, int step, int pre_i, int pre_j)

是拿上一步的pre_i和pre_j作为输入,然后我发现这样写没办法启动dfs,但是我当时脑子抽了,没找到直接输入i和j就能做出来的办法。所以只能第一步遍历所有格子的时候,把它写在dfs外面,总之有点愚蠢。但是,执行时间和内存都比我下一种写法要少很多,这是为啥?

(我自己写的)

复杂度:

代码:

#include <vector>
#include <string>
#include <iostream>
//我写的 dfs 剪枝 回溯
class solution {
public:
    solution(){}
    bool wordpuzzle(std::vector<std::vector<char>>& grid, std::string target) {
        n = target.size();
        if (n == 0 || grid.empty() || grid[0].empty())return false;
        rows = grid.size();//行
        cols = grid[0].size();//列
        int step = 1;
        vis = std::vector<int>(rows * cols);
        res = std::vector<char>(n);
        for (int i = 0; i < rows; ++i)//因为我写的dfs需要接受前一个dfs的位置i,j,为了启动,只能把第一轮遍历写在外面了
        {
            for (int j = 0; j < cols; ++j)
            {
                if (grid[i][j] == target[step - 1])
                {
                    res[step - 1] = grid[i][j];//访问
                    vis[i * cols + j] = 1;//标记
                    result = dfs(grid, target, step + 1, i, j);
                    if (result)return result;
                    vis[i * cols + j] = 0;//回溯
                    res[step - 1] = '\0';//回溯
                }
            }
        }
        return result;
    }
private:
    bool dfs(std::vector<std::vector<char>>& grid, std::string target, int step, int pre_i, int pre_j)
    {
        if (step == n + 1)return true;//中止条件 判断边界
        for (int i = 0; i < rows; ++i)//尝试每一种可能
        {
            for (int j = 0; j < cols; ++j)
            {
                if (vis[i * cols + j] == 0 &&//走过的不要
                    grid[i][j] == target[step-1]&&//不相同的直接不要
                    ((i * cols + j) == (pre_i * cols + pre_j - cols) ||//上
                        (i * cols + j) == (pre_i * cols + pre_j + cols) ||//下
                        (i == pre_i && j == pre_j - 1) ||//左
                        (i == pre_i && j == pre_j + 1)))//右
                {
                    res[step-1] = grid[i][j];//访问
                    vis[i * cols + j] = 1;//标记
                    result = dfs(grid, target, step + 1, i, j);//下一个
                    if (result)return result;
                    vis[i * cols + j] = 0;//回溯
                    res[step - 1] = '\0';//回溯
                }
            }
        }
        return result;
    }
    int n = 0;
    int rows = 0;
    int cols = 0;
    std::vector<int> vis;
    std::vector<char> res;
    bool result = false;
};

void test_solution1()
{
    solution solution;
    std::vector<std::vector<char>> grid{ { 'c','a','a'} ,{'a','a','a'},{'b','c','d'} };
    std::cout<< solution.wordpuzzle(grid ,std::string("aab"));

}

答案思路:

 把循环写到dfs外面了。

dfs判断的是当前的点。所以dfs是:

dfs(std::vector<std::vector<char>>& grid, std::string target, int step, int i, int j),

这里传进来的i和j是需要被判断的点,而不是我写的pre_i和pre_j

找方向用的是:

            result = dfs(grid, target, step + 1, i - 1, j) ||
                dfs(grid, target, step + 1, i + 1, j) ||
                dfs(grid, target, step + 1, i, j - 1) ||
                dfs(grid, target, step + 1, i, j + 1);

比我的好多了,呵呵。

但是测试的时间和内存异常多。然后我又测试了答案提供的,还是很多时间和内存,很奇怪啊。

 

看了答案之后自己根据思路重新写了一遍代码:

#include <vector>
#include <string>
#include <iostream>
//看了答案之后模仿写的 dfs 剪枝 回溯
//这个要用很多内存 呃,为什么?
class solution {
public:
    solution() {}
    bool wordpuzzle(std::vector<std::vector<char>>& grid, std::string target) {
        n = target.size();
        if (n == 0 || grid.empty() || grid[0].empty())return false;
        rows = grid.size();//行
        cols = grid[0].size();//列
        int step = 1;
        vis = std::vector<int>(rows * cols);
        //res = std::vector<char>(n);
        for (int i = 0; i < rows; ++i)//循环写在外面了
        {
            for (int j = 0; j < cols; ++j)
            {
                result = dfs(grid, target, step, i, j);
                if (result)return result;
            }
        }
        return result;
    }
private:
    bool dfs(std::vector<std::vector<char>>& grid, std::string target, int step, int i, int j)
    {
        if (step == n + 1)return true;//中止条件
        if (i >= 0 && i < rows && j >= 0 && j < cols &&//超过的不要
            vis[i * cols + j] == 0 &&//走过的不要
            grid[i][j] == target[step - 1])//不相同的直接不要
        {
            //res[step - 1] = grid[i][j];//访问
            vis[i * cols + j] = 1;//标记
            result = dfs(grid, target, step + 1, i - 1, j) ||
                dfs(grid, target, step + 1, i + 1, j) ||
                dfs(grid, target, step + 1, i, j - 1) ||
                dfs(grid, target, step + 1, i, j + 1);
            if (result)return result;
            vis[i * cols + j] = 0;
            //res[step - 1] = '\0';
        }
        return result;
    }
    int n = 0;
    int rows = 0;
    int cols = 0;
    std::vector<int> vis;
    //std::vector<char> res;
    bool result = false;
};

void test_solution2()
{
    solution solution;
    std::vector<std::vector<char>> grid{ { 'c','a','a'} ,{'a','a','a'},{'b','c','d'} };
    std::cout << solution.wordpuzzle(grid, std::string("aab"));

}

测试结果:

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

算法数据结构基础——哈希表(Hash Table)

08-06

算法基础5:哈希表、有序表、链表

08-06

2. 基础数据结构之哈希表

08-06

-哈希表-

08-06

数据结构之《二叉树》(中)

08-06

数据结构奇妙旅程之二叉树初阶

08-06

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论