C++使用回溯法解决黄金矿工问题

 更新时间:2022年10月08日 09:57:08   作者:刘婉晴  
在矩阵中考察回溯算法,分为任意起点、左上角开始等情况。从而有不同的模板,其实区别就是直接开始还是每个坐标都去尝试,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

顺心的人大抵一样,坎坷的人各有各的坎坷。也只能坚持自我修行,等待自己的机遇。

题目描述

你要开发一座金矿,地质勘测学家已经探明了这座金矿中的资源分布,并用大小为 m * n 的网格 grid 进行了标注。每个单元格中的整数就表示这一单元格中的黄金数量;如果该单元格是空的,那么就是 0。

为了使收益最大化,矿工需要按以下规则来开采黄金:

  • 每当矿工进入一个单元,就会收集该单元格中的所有黄金。
  • 矿工每次可以从当前位置向上下左右四个方向走。
  • 每个单元格只能被开采(进入)一次。
  • 不得开采(进入)黄金数目为 0 的单元格。
  • 矿工可以从网格中 任意一个 有黄金的单元格出发或者是停止。

链接:https://leetcode.cn/problems/path-with-maximum-gold (力扣)

示例

解题思路

这是一道典型的矩阵 回溯 的题目,依旧是回溯三步走:

1. 回溯函数参数:

  • int[][] grid 表示金矿的矩阵
  • int gold 表示当前路径收集到的金子的总和
  • int x, int y 表示收集到了第 grid[x][y] 位置

下面让我们来思考一个问题:本题需要建立一个 boolean[][] used 备忘录嘛?

备忘录是一定需要的,但是对本题来说,可以通过把已经遍历过的 grid[x][y] 的值改为 0,以此来实现备忘录,这样更能节省空间。

2. 结束条件:

当前遍历位置(x,y)越界,或者当前遍历位置没有金子(grid[x][y] == 0)时,结束return。

3. 单层逻辑:

int temp = grid[x][y]; // 记录值,以便回溯时恢复
gold += grid[x][y]; // 将当前值加入 gold 和中
max = Math.max(max, gold); // 更新结果
grid[x][y] = 0; // 将 grid[x][y] 置为0,防止出现同一重复重复使用

然后递归调用4次 dfs()函数,分布对应从 (x,y)向上下左右前进

回溯部分:

grid[x][y] = temp; // 回溯,恢复 grid[x][y] 

代码:

class Solution {
    int max = Integer.MIN_VALUE;
    public int getMaximumGold(int[][] grid) {
        for(int i=0; i<grid.length; i++){
            for (int j=0; j<grid[0].length; j++){
                if(grid[i][j] != 0) { // 从每个非0位置都可以开始
                    dfs(grid, 0, i, j);
                }
            }
        }
        return max==Integer.MIN_VALUE?0:max;
    }
    public void dfs(int[][] grid, int gold, int x, int y){
        if(!isOk(grid, x, y)){ // 判断是否越界或到无金子位置,结束
            return;
        }
        int temp = grid[x][y];
        gold += grid[x][y];
        max = Math.max(max, gold); // 更新最大值
        grid[x][y] = 0; // 防止出现重复遍历
        dfs(grid, gold, x+1, y); //向上
        dfs(grid, gold, x-1, y); //向下
        dfs(grid, gold, x, y+1); //向左
        dfs(grid, gold, x, y-1); // 向右
        grid[x][y] = temp; // 回溯
    }
	// 判断是否越界 或 走到了无金子位置
    public boolean isOk(int[][] grid, int x, int y){
        if(x<0 || x>=grid.length || y<0 || y>=grid[0].length || grid[x][y] == 0){
            return false;
        }
        return true;
    }
}

本题类似的题还有岛屿问题,可以移步到 岛屿问题

到此这篇关于C++使用矩阵回溯法解决黄金矿工问题的文章就介绍到这了,更多相关C++黄金矿工内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++中memcpy函数的使用以及模拟实现

    C++中memcpy函数的使用以及模拟实现

    memcpy是c和c++使用的内存拷贝函数,本文主要介绍了C++中memcpy函数的使用以及模拟实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 对比C语言中的setbuf()函数和setvbuf()函数的使用

    对比C语言中的setbuf()函数和setvbuf()函数的使用

    这篇文章主要介绍了对比C语言中的setbuf()函数和setvbuf()函数的使用,涉及到缓冲区与流的相关知识,需要的朋友可以参考下
    2015-08-08
  • Qt5+QMediaPlayer实现音乐播放器的示例代码

    Qt5+QMediaPlayer实现音乐播放器的示例代码

    这篇文章主要为大家详细介绍了如何利用Qt5和QMediaPlayer实现简易的音乐播放器,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下
    2022-12-12
  • opencv实现轮廓高斯滤波平滑

    opencv实现轮廓高斯滤波平滑

    这篇文章主要为大家详细介绍了opencv实现轮廓高斯滤波平滑,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • VC下通过系统快照实现进程管理的方法

    VC下通过系统快照实现进程管理的方法

    这篇文章主要介绍了VC下通过系统快照实现进程管理的方法,较为详细的讲述了VC下通过系统快照实现进程管理的原理与具体实现方法,非常具有实用价值,需要的朋友可以参考下
    2014-10-10
  • Qt使用QSoundEffect类实现播放音效或音乐

    Qt使用QSoundEffect类实现播放音效或音乐

    这篇文章主要为大家详细介绍了Qt如何使用QSoundEffect类实现播放音效或音乐功能,文中的示例代码讲解详细,有需要的小伙伴可以参考一下
    2024-12-12
  • C语言实现简单弹跳小球

    C语言实现简单弹跳小球

    这篇文章主要为大家详细介绍了C语言实现简单弹跳小球,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • 如何实现一定概率选中某一个字母

    如何实现一定概率选中某一个字母

    本篇文章是对如何实现一定概率选中某一个字母的解决方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C语言摄氏度互相转换华氏

    C语言摄氏度互相转换华氏

    这篇文章主要介绍了C语言摄氏度互相转换华氏,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • 基于c++计算矩形重叠面积代码实例

    基于c++计算矩形重叠面积代码实例

    这篇文章主要介绍了基于c++计算矩形重叠面积代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07

最新评论