![](/img/trans.png)
[英]Why does boost::scoped_ptr not work in inheritance scenario?
[英]Why does only backtracking work in this scenario?
我在LeetCode.com上解决这个问题:
在大小为 m * n 的金矿网格中,该矿中的每个单元格都有一个 integer 代表该单元格中的黄金数量,如果为空则为 0。 返回您在以下条件下可以收集的最大金币数量:-
(a) 每次您进入一个牢房时,您都会收集该牢房中的所有黄金;
(b) 从 position 开始,您可以向左、向右、向上或向下走一步。
(c) 你不能多次访问同一个牢房;
(d) 永远不要访问金币为 0 的牢房。
(e) 您可以开始和停止从有一些金币的网格中的任何 position 收集金币。
对于网格:[[0,6,0],[5,8,7],[0,9,0]]
output 是: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), max(dig(grid, i-1, j), dig(grid, i, 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, i, j));
gridCopy=grid;
}
}
}
return maxGold;
}
};
但是,它在输入[[1,0,7,0,0,0],[2,0,6,0,1,0],[3,5,6,7,4,2],[4,3,1,0,2,0],[3,0,5,0,20,0]]
; 产生58
而不是60
。
我在这里找到了另一个代码,它是相同的,除了上面的注释部分,其中它们有以下几行:
g[i][j] = -g[i][j];
auto res = max({ dfs(g, i + 1, j), dfs(g, i, j + 1), dfs(g, i - 1, j), dfs(g, i, j - 1) });
g[i][j] = -g[i][j];
return g[i][j] + res;
(当然,他们不会在嵌套的 for 循环中将grid
分配给gridCopy
,因为它们会将修改后的网格恢复为其原始形式)。
我知道他们在回溯,而我没有。 但是我无法理解我做错了什么,因为从逻辑上讲,我正在做同样的事情。 我使用调试语句来跟踪问题,但由于有很多递归调用,因此很难跟进。
有人可以指出我上面的代码中的逻辑谬误是什么吗?
谢谢!
您所有的递归调用都可能会修改网格,而不是恢复它。
这意味着对单元的第一次访问将阻止它进行所有其他后续尝试。
例如,如果首先评估dig(grid, i+1, j)
,则在执行其他三个方向时,在该计算期间访问的所有单元格都不可用。
如果您的代码恰好在您的示例中从左上角开始并且 go 首先向下,您将访问 1-2-3-4-3 并卡住。
在那次步行之后,从左上角开始就没有路径了,尽管一开始就有很多,其中一些支付的费用远远超过 13。
(您可能认为您会从任一方向找到路径,但这取决于评估顺序。)
共享可变 state 和递归是一个非常棘手的组合。
您的代码中似乎有问题的一件事是:
//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), max(dig(grid, i-1, j), dig(grid, i, j-1))));
return gold;
//change ends...
在这里,您已经改变了grid[i][j]
的值,并且改变的值正在影响您的输入,即您的输入集现在是错误的。 由于grid[i][j]
的值发生了变化,因此这将影响计算的 rest。
您可以做的是将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, i+1, j), max(dig(grid, i, j+1), max(dig(grid, i-1, j), dig(grid, i, j-1))));
grid[i][j] = temp;
return gold;
//change ends...
如果您在问题中使用解决方案,您还可以保存在递归堆栈中创建 memory。
只是为了回答您的问题,为什么只有回溯可以解决此问题:
您需要了解您的解决方案,如下所示:
grid[2][3]
。 您已将其标记为0
,即该节点的计算将 go 错误。 因此,您需要将原始值恢复到网格项grid[i][j]
。 您制作0
的原因是您不想再次包含它,因为您已经访问过。 但是对于其他解决方案集,您需要在其中存在原始值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.