Algorithm 算法方法-在网格中找到最佳路径
问题:有一个mxn网格(0你的问题称为a 当您达到(x,y)时,您可以拥有的最多硬币数量如下:Algorithm 算法方法-在网格中找到最佳路径,algorithm,graph-theory,dynamic-programming,Algorithm,Graph Theory,Dynamic Programming,问题:有一个mxn网格(0你的问题称为a 当您达到(x,y)时,您可以拥有的最多硬币数量如下: coins(x,y) = max(coins(x-1,y), coins(x,y-1)) + change 这是一个问题,可以通过使用递归和记忆来提高性能,也可以通过使用迭代算法来解决 迭代算法是一次遍历一条对角线。从0,0开始。然后计算0,1和1,0。然后计算0,2和1,1和2,0。等等 步骤1: 0, ?, ?, ? ?, ?, ?, ? ?, ?, ?, ? ?,
coins(x,y) = max(coins(x-1,y), coins(x,y-1)) + change
这是一个问题,可以通过使用递归和记忆来提高性能,也可以通过使用迭代算法来解决
迭代算法是一次遍历一条对角线。从0,0开始。然后计算0,1和1,0。然后计算0,2和1,1和2,0。等等
步骤1:
0, ?, ?, ?
?, ?, ?, ?
?, ?, ?, ?
?, ?, ?, ?
步骤2:
0, 23, ?, ?
13, ?, ?, ?
?, ?, ?, ?
?, ?, ?, ?
步骤3:
0, 23,-33, ?
13, 37, ?, ? // 37 because of max(23,13) + 14
36, ?, ?, ?
?, ?, ?, ?
等等
当您完成此过程时,答案是右下角的数字。您的问题可以描述为a,因此可以由解决 转变如下:
- 删除负节点并从相邻单元中减去它们的数量
- 0/0将是源,m-1,n-1将是接收器
- 每个节点连接到下方和右侧的节点,弧的容量等于其目标节点的值
- 现在,最大流量等于您可以拥有的最大硬币数量
MxN
最佳结果数组。用所有大的负值启动该数组,然后在你找到一个比已经解决的更好的解决方案时更新它。一旦你已经解决了使用完单元格后,将解决方案放入MxN
数组:下次递归时,检查数组中是否有数字,如果有值,则返回该值而不继续递归
记忆解决方案本身相当简单,算法的预处理步骤(从相邻单元格中减去负数)需要更多的代码
int solve(int r, int c) {
if(memo[r][c] != MIN) {
return memo[r][c];
}
int res = grid[r][c];
int a = 0, b = 0;
if (r+1 != R) {
a = solve(r+1, c);
}
if (c+1 != C) {
b = solve(r, c+1);
}
res = max(res+a, res+b);
return memo[r][c] = res;
}
这是打开的解决方案,它按预期返回
129
。有趣的问题。这是一个家庭作业问题吗?如果是,您需要将其标记为家庭作业。该问题仍将由社区进行评估。这不是家庭作业问题。我正在经历codechef的一个编程竞赛问题,我遇到了这个问题。我在连续两天都无法解决问题,但无法提出好的解决方案:-(如果你一开始就有网格的内容,这是一个带有加权边的图形生成问题。如果你移动到一个与多个强盗相邻的正方形,他们是否都拿走了你的一些硬币?你当前拥有的硬币数量会变为负数,还是会停止在0?找出最大流量是我遇到的问题。看就像我需要的算法一样。谢谢!我认为在这种情况下,流不会起作用,因为Ford Fulkerson会为您找到一条最佳路径,您可以在多条有效路径上同时收集硬币。例如,算法可能会将一部分流发送到右侧,如果剩余的流流网络将支持它,并且生成的流是最大的,但这与问题中的约束条件相反(您可以向右走,也可以向下走,但不能同时向右走和向下走)。是的,如果那样的话,它就不起作用了。不过我还是要检查一下那个算法。@dasblinkenlight:你当然是对的……我写那篇文章的时候很累;)一般来说,当有一个网格和多个查询时,记忆就起作用了(所以你不必再计算相同的东西)。这里只有一个查询。这就是我认为记忆化不起作用的原因。@Rushil这是错误的:当DP工作时,记忆化几乎在任何时候都能工作。你也会收到多个查询:它们来自你自己解决方案的递归调用。@Rushil特别是,简单的递归解决方案工作得不够快,因为它解决不了问题他一次又一次地解决同样的问题。通过计算一个解并存储它,你可以得到时间复杂度为O(M*N)。好吧,我得考虑一下。从m-1,n-1开始——将网格划分为多个阶段,并找出每个阶段每个单元要做出的最佳决策,我想这就是你所说的解决方案。我也这么想,但认为它行不通!我将尝试这个解决方案,并告诉你它是否被接受。谢谢
int solve(int r, int c) {
if(memo[r][c] != MIN) {
return memo[r][c];
}
int res = grid[r][c];
int a = 0, b = 0;
if (r+1 != R) {
a = solve(r+1, c);
}
if (c+1 != C) {
b = solve(r, c+1);
}
res = max(res+a, res+b);
return memo[r][c] = res;
}