Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 算法方法-在网格中找到最佳路径_Algorithm_Graph Theory_Dynamic Programming - Fatal编程技术网

Algorithm 算法方法-在网格中找到最佳路径

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, ?, ?, ? ?, ?, ?, ? ?, ?, ?, ? ?,

问题:有一个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,  ?,  ?,  ?
 ?,  ?,  ?,  ?
 ?,  ?,  ?,  ?
 ?,  ?,  ?,  ?
步骤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将是接收器
  • 每个节点连接到下方和右侧的节点,弧的容量等于其目标节点的值
  • 现在,最大流量等于您可以拥有的最大硬币数量
可能有更简单的解决办法,这只是我想到的第一件事

编辑:正如dasblinkenlight在评论中指出的那样,这是行不通的,因为流实际上是多条路径的组合,这当然不是我们想要的

我认为这个程序不能用动态规划来解决

为什么不呢?这是动态规划方法的主要候选者

简单的递归方法是我唯一能想到的,在给定的约束条件下,这种方法效率太低

你能建立一个递归的解决方案来解决,比如说,一个5x5网格吗?太好了!从这个开始,然后为你已经解决的单元格添加一个
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;
}