题目描述:
解题思路:
首先我们尝试着用暴力递归去解题,但是毫无疑问出现了超时无法提交成功,所以我们可以尝试一下dp
这是动态规划的一道经典例题,我们首先定义一个二维数组p[][]来表示到每个位置的路径条数,由题设我们可以看出,对于任意位置(x,y),只能由(x,y-1)向下走一步或者由位置(x-1,y)向右走一步到达,所以可以得到递推关系p[x][y]=p[x-1][y]+p[x][y-1],我们可以让p[0][0]=1,而p[m-1][n-1]就是我们要求的结果,这样做出来的时间复杂度和空间复杂度都是O(mn)
注意事项:
还有要注意的是,由于机器人只能向右或者向下,所以我们可以让p[0][i]和p[i][0]的值直接为1
代码:
int uniquePaths(int m, int n) {
int i,j;
int p[m][n];
for(i=0;i<m;++i)
{
p[i][0]=1;
}
for (j=0;j<n;++j)
{
p[0][j]=1;
}
for(i=1;i<m;++i)
{
for(j=1;j<n;++j)
{
p[i][j]=p[i-1][j]+p[i][j-1];
}
}
return p[m-1][n-1];
}
运行结果:
解法优化:
思路:
在创建二维数组的时候会占用较大的空间,所以我们可以尝试一下将二维数组压缩成一维数组进行dp,这样空间复杂度可以降为O(n)
原理;
在每次循环中p[j]是上一次循环时j位置数组的元素值,而p[j-1]的值是左边的值,相当于把二维数组压缩为一维数组
代码:
int uniquePaths(int m, int n) {
int i,j;
int p[n];
p[0] = 1;
if(m>n)
{
int t;
t=m;
m=n;
n=t;
} //交换m,n
for(i=1;i<n;i++)
{
p[i]=0;
}
for(i=0;i<m;i++)
{
for(j=1;j<n;j++)
{
p[j]+=p[j-1];
}
}
return p[n-1];
}
运行结果:
其他解法:
同样,我们也可以用到高中数学的排列组合方法来解这道题,由于机器人一共会走m+n-2步,那么直接m+n-2中挑出m-1步向下走即可,那么最终结果就是C(m-1)(m+n-2)
代码:
int uniquePaths(int m, int n) {
long long int path = 1;
for (int x = n, y = 1; y < m; ++x, ++y) {
path = path * x / y;
}
return path;
}
运行结果: 
知识点:
动态规划:动态规划常是用来求最优解的一种途径,在求全局最优解的过程中,分治思想是较为常见的一种解题途径,但如果子问题之间不独立,则适合用动态规划思想。而动态规划和贪心算法的不同之处是,动态规划是针对全局求最优解,而贪心算法是针对上一个最优解继续求最优解0。同时,由于在动态规划的过程中要存储各种状态,所以会占用更多空间,是一种以空间换时间的方法。在动态规划中,核心的步骤是找到数组元素之间的关系式