首先有过这类题经验的同学肯定知道这道题必然需要用到动态规划
下面就讲一下我的思路:(动态规划三步走)
- 首先我们肯定是需要开一个二维数组来表示,即dp[ i ][ j ]来表示到达(i,j)这个点的路径总数
- 其次我们需要根据题意推断出动态规划方程,我们知道机器人每次只能向下或者是向右走一步,那么我们可以知道方程就是dp[ i ][ j ]=dp[i-1][ j ]+dp[ i ][j-1] (和台阶问题一样道理,即我们走到某一步,该步肯定是由该步的上面或者左边走过来的)
- 最后就是初始化,很明显,该方程的i和j都是数组下标,它们都不能为负数,所以只要i=0或者j=0的位置(即最上面一行和最左边一列)的值我们都设为1(因为不论要走到哪一个格子,我们只有一种走法,即一直向右走或者一直向下走)
最后给出代码
int uniquePaths(int m, int n){
int i,j;
if(m<=0||n<=0)
{
return 0;
}
int dp[m][n];
for(i=0;i<m;i++)
{
dp[i][0]=1;
}
for(i=0;i<n;i++)
{
dp[0][i]=1;
}
for(i=1;i<m;i++)
{
for(j=1;j<n;j++)
{
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[m-1][n-1];
}
法2 DFS(对于该题会超时)
对于这种图的路径问题,DFS也是常见的做法
很明显该题的DFS出口即网格的右下角的点的坐标
class Solution {
public:
int tx,ty,cn=0,nextt[2][2]={{0,1},{1,0}};
int book[100][100]={0};//记录有没有走过
void dfs(int x,int y,int m,int n)
{
if(x==m-1&&y==n-1)//到达右下角
{
cn++;
return ;
}
if(!book[x][y])//这个点没走过
{
for(int i=0;i<2;i++)//往右边或下边走
{
tx=x+nextt[i][0];
ty=y+nextt[i][1];
if(tx<0||ty<0||tx>=m||ty>=n||book[tx][ty])//越界或走过
{
continue;
}
dfs(tx,ty,m,n);
book[tx][ty]=0;//记得恢复
}
}
}
int uniquePaths(int m, int n) {
dfs(0,0,m,n);
return cn;
}
};
法3 BFS
按照我们之前学习的模板来即可
class Solution {
public:
typedef pair<int, int> PII;
int uniquePaths(int m, int n) {
int f[101][101] = { 0 };//初始化
f[0][0] = 1;//初始化
queue<PII> q;
q.push({ 0, 0 });
int dx[2] = { 1, 0 };
int dy[2] = { 0, 1 };
while (!q.empty())
{
PII t = q.front();
q.pop();
for (int i = 0; i < 2; i++)
{
int x = t.first + dx[i];
int y = t.second + dy[i];
if (x >= 0 && x < n && y >= 0 && y < m)
{
if (f[x][y] == 0)//没走过
q.push({ x, y });
f[x][y] += f[t.first][t.second];//将该点的上面一点 与 该点的左边一点 的路径数相加
}
}
}
return f[n - 1][m - 1];
}
};
法4 数学
对数学敏感的同学可能会更容易想到该方法
我们在高中时期曾经学习过组合数的概念
具体思路如下
class Solution {
public:
int uniquePaths(int m, int n) {
long long ans = 1;
for (int x = n, y = 1; y < m; ++x, ++y) {
ans = ans * x / y;
}
return ans;
}
};