我试图用一种递归的方法来找到从nxn网格的左上角到右下角的所有单调路径的所有区域的总和(路径的每一步都可以向右或者沿着这条线。)
假设左下角有坐标(0,0),我有以下功能:
int sum(int current_sum, int x, int y, int n){
if (x == n || y == 0)
return current_sum;
return (sum(current_sum+y, x+1, y, n) + sum(current_sum, x, y-1, n));
}
,当它到达网格的右侧或底线时停止(从那里移动任何移动都不会改变区域的当前值)并考虑向右或向下移动产生的区域总和。结果比它应该的大,我在弄清楚原因时遇到了一些麻烦。有人可以看一下吗?
提前致谢
答案 0 :(得分:1)
再次阅读,OP的解决方案似乎已经是正确的。我的答案在下面作为参考。
这似乎是Project Euler problem 15,或者是一个非常类似的问题。
所以如果我理解你想要做的是这个:
以递归方式执行此操作将如下所示:
int area(int x, int y)
{
if (x == 0 || y == 0)
/* We are at the end of a path, terminate */
return 0;
/* We are not at the end, add the two choices possible from here */
return area(x, y - 1) + area(x - 1, y) + y;
}
您必须绘制一个数字才能看到最后一个表达式是正确的。当我们在网格(-x)中向右移动时,我们只将y加到总和上,从而覆盖了我们下面的一列。向下移动(-y)不会覆盖任何区域。
这个解决方案应该是正确的,但速度会非常慢。为了加快速度,您可以添加 memoisation ,这意味着将区域(x,y)的中间结果保存到表中并查找,而不是每次都计算它。我不会为你写那个解决方案,但这并不难。祝你好运。
答案 1 :(得分:1)
[..]从nxn网格的左上角到右下角 [..]
您的代码未反映出:
// ...
if (x == n || y == 0)
return current_sum;
// ...
想想一条完全水平的道路。例如,在2对3网格中,当索引从0
开始,左下角为(0 | 0)
时,右下角将为(1 | 0)
。现在考虑 upper 右上角,即(1 | 2)
。上述两个条件都不适用于这些值,因此您总结了下两个单元格的递归调用:(2 | 2)
(向右)和(1 | 1)
(向下)。
第一个单元格(右边)是问题:那里,x == 2 == n
因此你返回路径的总和虽然它没有在右下角结束。因此,您将太多路径相加,导致总和过大。
我认为应该这样做:
unsigned sum_inner(
unsigned const accumulatedSum,
size_t const x, size_t const y,
size_t const gridSideSize) {
bool atRightEdge = (x == gridSideSize - 1);
bool atBottomEdge = (y == 0);
if (atRightEdge && atBottomEdge) {
// Awesome, in lower right corner, so everything is fine
// Except that with the implementation of the other two edge cases, this
// will never be run (except for the 1x1 case)!
printf("reached lower right edge!\n");
return accumulatedSum + 1;
} else if (atRightEdge) {
// Right edge, so from here one can only go down. Since there's only one
// possible path left, sum it directly:
return accumulatedSum + y + 1;
} else if (atBottomEdge) {
// Bottom edge, so from here one can only go right. Since there's only one
// possible path left, sum it directly:
return accumulatedSum + (gridSideSize - x) + 1;
} else {
// Somewhere in the grid, recursion time!
return sum_inner(accumulatedSum + y, x + 1, y, gridSideSize) +
sum_inner(accumulatedSum, x, y - 1, gridSideSize);
}
}
unsigned sum_monotonic_tl_br(size_t const gridSideSize) {
return sum_inner(0, 0, gridSideSize - 1, gridSideSize);
}