为什么在这种情况下只能回溯?

如何解决为什么在这种情况下只能回溯?

我正在LeetCode.com上解决此问题:

在大小为m * n的金矿网格中,该矿中的每个单元都有一个整数,表示该单元中的金量;如果为空,则为0。返回在以下条件下可以收集的最大黄金量:-
(a)每次位于一个牢房中时,您都将收集该牢房中的所有黄金;
(b)从您的位置可以向左,向右,向上或向下走一步。
(c)您不能多次访问同一个单元;
(d)切勿访问零金的牢房。
(e)您可以从网格中任何有金的位置开始和停止收集金。
对于网格:[[0,6,0],[5,8,7],[0,9,0]],输出为:24

我写了下面的代码:

class Solution {
public:
    int dig(vector<vector<int>>& grid,int i,int j) {
        if(i>=grid.size() || i<0 || j>=grid[0].size() || j<0 || grid[i][j]==0) return 0;
        
        //change begins...
        int gold=0;
        gold+=grid[i][j];
        grid[i][j]=0;
        gold+=max(dig(grid,i+1,j),max(dig(grid,i,j+1),i-1,dig(grid,j-1))));
        return gold;
        //change ends...
    }
    
    int getMaximumGold(vector<vector<int>>& grid) {
        vector<vector<int>> gridCopy=grid;
        
        int maxGold=0;
        for(int i=0; i<grid.size(); i++) {
            for(int j=0; j<grid[0].size(); j++) {
                if(grid[i][j]!=0) {
                    maxGold=max(maxGold,dig(gridCopy,j));
                    gridCopy=grid;
                }
            }
        }
        
        return maxGold;
    }
};

但是,它在输入[[1,7,[2,1,[3,5,4,2],[4,3,2,20,0]]处中断;产生58而不是60

我发现了另外一个here的代码,除了上面的注释部分外,它们是相同的,而它们具有以下几行:

  g[i][j] = -g[i][j];
  auto res = max({ dfs(g,i + 1,dfs(g,j + 1),i - 1,j - 1) });
  g[i][j] = -g[i][j];
  return g[i][j] + res;

(当然,他们不会在嵌套的for循环中将grid分配给gridCopy,因为它们会将修改后的网格恢复为原始格式)。

我知道他们正在回溯,而我不是。但是我无法理解我在做什么错,因为从逻辑上讲,我在做完全相同的事情。我使用了调试语句来跟踪问题,但是由于有许多递归调用,因此很难遵循。

有人可以指出我上面的代码中的逻辑谬误是什么吗?

谢谢!

解决方法

您所有的递归调用都可能会修改网格,而不恢复网格。
这意味着,第一次访问该单元将阻止该单元进行其他所有后续尝试。

例如,如果首先评估dig(grid,i+1,j),则在执行其他三个方向时,在该计算过程中访问的所有单元都不可用。

如果您的代码碰巧从左上角开始,然后在示例中首先向下移动,则您将访问1-2-3-4-3并陷入困境。
步行之后,即使从一开始便有很多东西,但从左上角再也没有路径了,其中有些人的薪水远高于13。
(您可能会认为您会从任一方向找到一条路径,但这取决于评估顺序。)

共享的可变状态和递归是非常棘手的组合。

,

您的代码中似乎有错的一件事是:

//change begins...
        int gold=0;
        gold+=grid[i][j];
        grid[i][j]=0;
        gold+=max(dig(grid,j),max(dig(grid,i,j+1),i-1,dig(grid,j-1))));
        return gold;
        //change ends...

在这里,您已经更改了grid[i][j]的值,而更改后的值正在影响您的输入,即您的输入集现在是错误的。由于grid[i][j]的值已更改,因此将影响其余的计算。

您可以做的是将grid[i][j]的初始值存储在该递归堆栈中的某个位置,并在完成从该节点的所有路径探索之后将其重新分配回grid[i][j]

例如:您的逻辑稍作修改

//change begins...
        int gold=0;
        gold+=grid[i][j];
        int temp = grid[i][j];
        grid[i][j]=0;
        gold+=max(dig(grid,j-1))));
        grid[i][j] = temp;
        return gold;
        //change ends...

如果您在问题中使用那里的解决方案,还可以在递归堆栈中保存创建内存的操作。

只需回答您的问题,为什么只有回溯才能解决此问题:

您需要了解您的解决方案,如下所示:

  • 查看每个网格项目是否可以作为解决方案集的一部分。
  • 为此,您选择一个网格项目(项目值应大于0)
  • 然后,您可以探索该项目的所有周围环境。并使用DFS继续探索周围环境和周围环境等,直到满足退出条件为止。
  • 现在,在您的解决方案中,您已经对grid [i] [j]的值进行了变异(出于理解目的,我们说grid [2] [3]被变异了)出现在最终解决方案集中。
  • 但是,在探索其他可能性时,如果您碰巧发现存在更多黄金的可能性。然后还将涉及grid[2][3]。您已将其标记为0,即该节点的计算将出错。

因此,您需要将原始值恢复到网格项目grid[i][j]。您之所以选择0是因为您不想再访问它了,因为您已经访问过它。但是对于其他解决方案集,您需要在其中存在原始值。

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

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-