[..] 从 nxn 网格的左上角到 右下角 [..]
您的代码没有反映:
// ...
if (x == n || y == 0)
return current_sum;
// ...
想象一条完全水平的路径。例如,在 2 on 3 网格中,当索引以 0 开头且左下角为 (0 | 0) 时,右下角将为 (1 | 0)。现在考虑右上角,即(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);
}
(Live with sizes from 1 to 15)