【发布时间】:2015-11-15 14:06:42
【问题描述】:
我正在解决this problem,其中要求我提供 20 x 20 网格中从一个角到另一个角的最短路径数。我知道这是一个简单的组合问题,但我面临的挑战是实现一个解决它的方法。
我的想法是使用递归:到网格点 (m,n) 的路径数等于到 (m-1,n) 的路径数加上到 (m,n-1) 的路径数.我从以下代码开始:
using System;
class Program
{
static void Main()
{
long noOfPaths = CountPaths(15, 15);
Console.WriteLine(noOfPaths);
Console.ReadKey();
}
static long CountPaths(int m, int n)
{
if (m == 0) return 1;
else if (n == 0) return 1;
return CountPaths(m-1,n) + CountPaths(m,n-1);
}
}
这很好用,并返回正确数量的路径,但是随着网格大小的增加,它的运行时间会急剧增加,而且我无法达到 20x20。上述的主要问题之一是它不止一次地在同一个网格点上进行递归调用,我想要一些关于跟踪这一点的最佳方法的建议。到目前为止,我已经在这个站点周围找到了关于“全局变量”的帖子,我的解决方案是创建一个可以从任何地方访问的数组。下面的代码解决了我的问题,而且速度也相当快。
using System;
namespace problem15
{
class Program
{
static void Main()
{
long noOfPaths = CountPaths(Values.m-1, Values.n-1);
Console.WriteLine(noOfPaths);
Console.ReadKey();
}
static long CountPaths(int m, int n)
{
if (m == 0) return 1;
else if (n == 0) return 1;
if (Values.A[m - 1, n] == 0) Values.A[m - 1, n] = CountPaths(m - 1, n);
if (Values.A[m, n - 1] == 0) Values.A[m, n - 1] = CountPaths(m, n - 1);
return Values.A[m-1,n] + Values.A[m,n-1];
}
}
static class Values
{
static public int m = 21, n = 21;
static public long[,] A = new long[m, n];
}
}
这是解决问题的好方法,还是被认为是“糟糕的形式”?另外,我知道这个问题还有更多的优化,例如到 (k,l) 的路径数与到 (l,k) 的路径数相同。
【问题讨论】:
-
解决此问题的常用方法是使用 动态编程 解决方案之一(使用记忆的递归 - 在 C# 中不推荐)或使用表格 - 只需 google 即可获得 动态规划 你会很快找到这个确切的问题
-
@Carsten 谢谢。据我所知,动态编程是将解决方案保存到您已经完成的子问题中,如果稍后出现子问题,您将使用保存的解决方案而不是重新计算它。在我看来,这类似于我对问题的第二种解决方案所做的。
-
这比 StackOverflow 更适合 CodeReview。