この問題を解決するにはさまざまな方法がありますが、私が使用した 2 つの方法は次のとおりです。
- 順列法
- 動的プログラミング
方法 1: 順列と組み合わせ
- まずこの例を見てください。m=3 は行を意味し、n=7 は列を意味します。
- すると、右下隅に到達するためには、ロボットの動作経路は下に移動するのに 2 ステップ、右に移動するのに 6 ステップだけ必要であることは想像に難くありません。右隅。
- 最後に、順列と組み合わせによってパスの数を計算することができ、ロボットは 8 つのステップを移動する必要があり、そのうち 2 つは下に、6 つは右に移動します。次の式を組み合わせて、8 つのステップのうち 2 つを選択して下に進みます。
上記の例の一般的な状況に対応すると、次のようになります。
- m と n がわかると、ロボットが下に移動するステップ数は (m-1)、右に移動するステップ数は (n-1)、移動する合計ステップ数は次のようになります。 (m-1+n-1 )=(m+n-2) 。
- 一般的な場合の結合式を取得します。
上記の一般式から、任意の m と n に対応するパスの数を直接計算できます。
階乗を計算するための fastial() 関数は、Python の数学ライブラリで提供されています。
(私は C++ の階乗関数を知りません。ここでは Python を使用して回答するだけですが、階乗関数を自分で書くことも非常に簡単です)
Pythonを使用した答えは次のとおりです。
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
"""排列组合方法"""
return int(math.factorial(m+n-2)/(math.factorial(m-1)*math.factorial(n-1)))
方法 2: 動的プログラミング
引き続き上記の例を使用して紹介します。
- m×n グリッドの場合、m×n 行列を構築できます。行列内の各要素の値は、ロボットが開始点から要素の位置までたどるパスの数を表します。(各要素を 0 にシリング)
0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 |
- 最初の行の要素ごとに、ロボットが到達できるパスは 1 つだけあり、それは右端まで移動することです。最初の列の要素についても、ロボットが到達できるパスは 1 つだけです。一番下まで移動します。したがって、最初の行と最初の列の要素には値 1 を割り当てることができます (これが動的計画法の初期条件です)。
1 | 1 | 1 | 1 | 1 | 1 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 |
- 他の位置にある要素の場合、この要素に到達するには 2 つのパスしかないことがわかります。つまり、要素の上部から下に移動するか、要素の左側から右に移動することです。したがって、この要素に到達するパスの数は、この要素の左側の要素の値にこの要素の上の要素の値を加えたものに等しいことがわかります。(これは動的計画法の再帰公式です)
1 | 1 | 1 | 1 | 1 | 1 | 1 |
1 | 2 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 |
- したがって、すべての要素の値を計算することができます
1 | 1 | 1 | 1 | 1 | 1 | 1 |
1 | 2 | 3 | 4 | 5 | 6 | 7 |
1 | 3 | 6 | 10 | 15 | 21 | 28 |
- この時点で、行列の最後の要素の値は、始点から終点までのパスの総数である 28 を表します。
Python を使用した答えは次のとおりです。
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
"""动态规划求解不同路径"""
# 创建一个m×n的矩阵,每个元素都为0
N = [0 for _ in range(n)] # 创建长度为n的列表,每个元素都为0
M = [N for _ in range(m)] # 创建长度为m的列表,每个元素都为列表n
for i in range(n):
M[0][i] = 1 # 将矩阵第一行元素赋值为1
for i in range(m):
M[i][0] = 1 # 将矩阵第一列元素赋值为1
for i in range(1, m):
for j in range(1, n):
# 除去第一行和第一列的每个元素的值,都等于其左侧和正上方值的和
M[i][j] = M[i][j-1] + M[i-1][j]
return M[-1][-1] # 返回最后一列最后一行元素,即总共的路径数
C++ を使用した答えは次のとおりです。
class Solution {
public:
int uniquePaths(int m, int n) {
vector<int> N(n, 0);
vector<vector<int>> M(m, N);
for(int i=0; i<N.size();i++){
M[0][i] = 1;
}
for(int i=0; i<M.size();i++){
M[i][0] = 1;
}
for(int i=1; i<M.size();i++){
for(int j=1; j<N.size();j++){
M[i][j] = M[i][j-1] + M[i-1][j];
}
}
return M.back().back();
}
};