Re-translate the Japanese version (#1871)

* Retranslate Japanese docs with GPT-5.4

* Retranslate Japanese code with GPT-5.4
This commit is contained in:
Yudong Jin
2026-03-30 07:30:15 +08:00
committed by GitHub
parent fe6443235b
commit d7b2277d2b
1444 changed files with 83312 additions and 8363 deletions

View File

@@ -1,28 +1,28 @@
# 無制限ナップサック問題
# 完全ナップサック問題
このセクションでは、まず別の一般的なナップサック問題である無制限ナップサックを解決し、次にその特殊ケースであるコイン交換問題を探索します。
本節では、まずもう 1 つの代表的なナップサック問題である完全ナップサック問題を解き、その特殊例である硬貨交換問題について見ていきます。
## 無制限ナップサック問題
## 完全ナップサック問題
!!! question
$n$ 個のアイテムが与えられ、$i$ 番目のアイテムの重は $wgt[i-1]$値は $val[i-1]$ です。容量 $cap$ のバックパックがあります。**各アイテムは複数回選択できます**。容量を超えることなくバックパックに入れることができるアイテムの最大値は何ですか?以下の例を参照してください
$n$ 個の品物が与えられ、$i$ 番目の品物の重は $wgt[i-1]$、価値は $val[i-1]$ であり、容量 $cap$ のナップサックがあります。**各品物は繰り返し選択できます**。ナップサック容量の制約下で入れられる品物の最大価値を求めてください。例を以下の図に示します
![無制限ナップサック問題のデータ](unbounded_knapsack_problem.assets/unbounded_knapsack_example.png)
![完全ナップサック問題のサンプルデータ](unbounded_knapsack_problem.assets/unbounded_knapsack_example.png)
### 動的プログラミングアプローチ
### 動的計画法の考え方
無制限ナップサック問題は0-1ナップサック問題と非常に似ており、**唯一の違いはアイテムを選択できる回数に制限がないことです**。
完全ナップサック問題は 0-1 ナップサック問題と非常によく似ています。**違いは、品物の選択回数に制限がない点だけです**。
- 0-1ナップサック問題では、各アイテムは1つしかないため、アイテム $i$ をバックパックに入れた後は、前の $i-1$ 個のアイテムからのみ選択できます
- 無制限ナップサック問題では、各アイテムの数は無限であるため、アイテム $i$ をバックパックに入れた後も、**前の $i$ 個のアイテムから引き続き選択できます**。
- 0-1 ナップサック問題では、各品物は 1 つしかないため、品物 $i$ をナップサックに入れた後は先頭 $i-1$ 個の品物からしか選べません
- 完全ナップサック問題では、各品物の数は無限であるため、品物 $i$ をナップサックに入れた後も、**引き続き先頭 $i$ 個の品物から選べます**。
無制限ナップサック問題のルールの下で、状態 $[i, c]$ は2つの方法で変化できます。
完全ナップサック問題で、状態 $[i, c]$ の変化は 2 つの場合に分けられます。
- **アイテム $i$ を入れない**0-1ナップサック問題と同様に、$[i-1, c]$ 遷移します。
- **アイテム $i$ を入れる**0-1ナップサック問題とは異なり、$[i, c-wgt[i-1]]$ 遷移します。
- **品物 $i$ を入れない** 0-1 ナップサック問題と同様に、$[i-1, c]$ 遷移します。
- **品物 $i$ を入れる** 0-1 ナップサック問題とは異なり、$[i, c-wgt[i-1]]$ 遷移します。
したがって、状態遷移方程式は次のようになります
したがって、状態遷移方程式は次のようになります
$$
dp[i, c] = \max(dp[i-1, c], dp[i, c - wgt[i-1]] + val[i-1])
@@ -30,7 +30,7 @@ $$
### コード実装
2つの問題のコードを比較すると、状態遷移 $i-1$ から $i$ に変わり、残りは完全に同です
2 つの問題のコードを比較すると、状態遷移の中で 1 か所だけ $i-1$ $i$ に変わり、それ以外は完全に同です
```src
[file]{unbounded_knapsack}-[class]{}-[func]{unbounded_knapsack_dp}
@@ -38,12 +38,12 @@ $$
### 空間最適化
現在の状態は左と上の状態からるため、**空間最適化解法は $dp$ テーブルの各行に対して前方走査を実行する必要があります**。
現在の状態は左と上の状態から遷移してくるため、**空間最適化は $dp$ テーブルの各行を順方向に走査する必要があります**。
この走査順序は0-1ナップサックの場合とは逆です。違いを理解するために下の図を参照してください。
この走査順序は 0-1 ナップサックとはちょうど逆です。両者の違いは次の図を用いて理解してください。
=== "<1>"
![空間最適化後の無制限ナップサック問題の動的プログラミングプロセス](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step1.png)
![完全ナップサック問題における空間最適化後の動的計画法の過程](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step1.png)
=== "<2>"
![unbounded_knapsack_dp_comp_step2](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step2.png)
@@ -60,67 +60,67 @@ $$
=== "<6>"
![unbounded_knapsack_dp_comp_step6](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step6.png)
コード実装は非常に簡単で、配列 `dp`最初の次元を削除するだけです
コード実装は比較的簡単で、配列 `dp`第 1 次元を削除するだけです
```src
[file]{unbounded_knapsack}-[class]{}-[func]{unbounded_knapsack_dp_comp}
```
## コイン交換問題
## 硬貨交換問題
ナップサック問題は動的プログラミング問題の大きなクラスの代表であり、コイン交換問題など多くの変種があります。
ナップサック問題は動的計画法の代表的な問題群であり、多くの派生問題があります。硬貨交換問題もその 1 つです。
!!! question
$n$ 種類のコインが与えられ、$i$ 番目の種類のコインの額面は $coins[i - 1]$ 、目標金額は $amt$ です。**各種類のコインは複数回選択できます**。目標金額を構成するのに必要な最小コイン数は何ですか?目標金額を構成できない場合は $-1$ を返してください。以下の例を参照してください
$n$ 種類の硬貨が与えられ、$i$ 番目の硬貨の額面は $coins[i - 1]$ 、目標金額は $amt$ です。**各硬貨は繰り返し選択できます**。目標金額を作るために必要な最小の硬貨枚数を求めてください。目標金額を作れない場合は $-1$ を返します。例を以下の図に示します
![コイン交換問題のデータ](unbounded_knapsack_problem.assets/coin_change_example.png)
![硬貨交換問題のサンプルデータ](unbounded_knapsack_problem.assets/coin_change_example.png)
### 動的プログラミングアプローチ
### 動的計画法の考え方
**コイン交換は無制限ナップサック問題の特殊ケースと見なすことができ**、以下の類似点と相違点を共有しています。
**硬貨交換は完全ナップサック問題の特殊ケースとみなせます**。両者には次の対応関係と相違点があります。
- 2つの問題は互に変換できます:「アイテム」は「コイン」に対応し、「アイテムの重」は「コインの額面」に対応し、「バックパック容量」は「目標金額」に対応します。
- 最適化目標は逆です:無制限ナップサック問題はアイテムの値を最大化することを目的とし、コイン交換問題はコインの数を最小化することを目的とします。
- 無制限ナップサック問題はバックパック容量を「超えない」解を求め、コイン交換は目標金額を「正確に」構成する解を求めます。
- 2 つの問題は互に変換でき、「品物」は「硬貨」、「品物の重」は「硬貨の額面」、「ナップサック容量」は「目標金額」に対応します。
- 最適化目標は逆であり、完全ナップサック問題は品物価値の最大化、硬貨交換問題は硬貨枚数の最小化を目指します。
- 完全ナップサック問題はナップサック容量を「超えない」解を求めますが、硬貨交換は目標金額に「ちょうど」一致する解を求めます。
**第1ステップ:各ラウンドの意思決定を考え、状態を定義し、それにより $dp$ テーブルを導出す**
**ステップ 1:各ラウンドの選択を考え、状態を定義し、$dp$ テーブルを**
状態 $[i, a]$ は部分問題に対応します:**最初の $i$ 種類のコインを使用して金額 $a$ を構成できる最小コイン数**、$dp[i, a]$ と表記されます。
状態 $[i, a]$ に対応する部分問題は、**先頭 $i$ 種類の硬貨で金額 $a$ を作るための最小硬貨枚数**であり、これを $dp[i, a]$ と表ます。
次元 $dp$ テーブルのサイズは $(n+1) \times (amt+1)$ です。
2 次元 $dp$ テーブルのサイズは $(n+1) \times (amt+1)$ です。
**第2ステップ:最適部分構造を特定し、状態遷移方程式を導出する**
**ステップ 2:最適部分構造を見つけ、状態遷移方程式を導**
この問題は状態遷移方程式の2つの側面で無制限ナップサック問題と異なります。
本問の状態遷移方程式は、完全ナップサック問題と比べて次の 2 点が異なります。
- この問題は最小値を求めるため、演算子 $\max()$ を $\min()$ に変更する必要があります。
- 最適化はコインの数に焦点を当てているため、コインが選択されたときに単純に $+1$ を追加します。
- 本問では最小値を求めるため、演算子 $\max()$ を $\min()$ に変更する必要があります。
- 最適化の対象は品物価値ではなく硬貨枚数であるため、硬貨を選んだときは $+1$ すれば十分です。
$$
dp[i, a] = \min(dp[i-1, a], dp[i, a - coins[i-1]] + 1)
$$
**第3ステップ:境界条件と状態遷移順序を定義す**
**ステップ 3:境界条件と状態遷移順序を決め**
目標金額が $0$ の場合、それを構成するのに必要な最小コイン数は $0$ であるため、最初の列のすべての $dp[i, 0]$ は $0$ す。
目標金額が $0$ のとき、それを作るための最小硬貨枚数は $0$ です。つまり、先頭列のすべての $dp[i, 0]$ は $0$ になります。
コインがない場合、**任意の金額 >0 を構成することは不可能**であり、これは無効解です。状態遷移方程式の $\min()$ 関数が無効解を認識してフィルタリングできるように、$+\infty$ を使用してそれらを表現することを検討し、つまり最初の行のすべての $dp[0, a]$ を $+\infty$ に設定します。
硬貨が 1 枚もない場合、**任意の $> 0$ の目標金額を作ることはできません**。これは無効解です。状態遷移方程式の $\min()$ 関数が無効解を識別して除外できるように、それらを $+ \infty$ で表すことを考えます。すなわち、先頭行のすべての $dp[0, a]$ を $+ \infty$ します。
### コード実装
ほとんどのプログラミング言語は $+\infty$ 変数を提供しておらず、整数 `int` の最大値のみを代替として使用できます。これによりオーバーフローが発生する可能性があります状態遷移方程式の $+1$ 演算がオーバーフローする可能性があります。
多くのプログラミング言語は $+ \infty$ を表す変数が用意されていないため、通常は整数 `int` の最大値で代用します。しかし、その場合は大きな数のオーバーフローが起こり得ます状態遷移方程式の $+ 1$ 操作で桁あふれが発生する可能性があるためです。
この理由で、数値 $amt + 1$ を使用して無効な解を表します。なぜなら、$amt$ を構成するのに必要な最大コイン数は最大でも $amt$ だからです。結果を返す前に、$dp[n, amt]$ が $amt + 1$ に等しいかどうかを確認し、そうであれば $-1$ を返し目標金額を構成できないことをします。コードは以下の通りです
そのため、ここでは数値 $amt + 1$ を無効解の表現として用います。金額 $amt$ を作るための硬貨枚数は最大でも $amt$ だからです。最後に返す前に、$dp[n, amt]$ が $amt + 1$ に等しいかを判定し、等しければ $-1$ を返し目標金額を作れないことをします。コードは次のとおりです
```src
[file]{coin_change}-[class]{}-[func]{coin_change_dp}
```
の図はコイン交換問題の動的プログラミングプロセスを示しており、無制限ナップサック問題と非常に似ています。
の図は硬貨交換の動的計画法の過程を示しており、完全ナップサック問題と非常によく似ています。
=== "<1>"
![コイン交換問題の動的プログラミングプロセス](unbounded_knapsack_problem.assets/coin_change_dp_step1.png)
![硬貨交換問題の動的計画法の過程](unbounded_knapsack_problem.assets/coin_change_dp_step1.png)
=== "<2>"
![coin_change_dp_step2](unbounded_knapsack_problem.assets/coin_change_dp_step2.png)
@@ -166,31 +166,31 @@ $$
### 空間最適化
コイン交換問題の空間最適化は無制限ナップサック問題と同じ方法で処理されます:
硬貨交換の空間最適化の方法は、完全ナップサック問題と同じです。
```src
[file]{coin_change}-[class]{}-[func]{coin_change_dp_comp}
```
## コイン交換問題II
## 硬貨交換問題 II
!!! question
$n$ 種類のコインが与えられ、$i$ 番目の種類のコインの額面は $coins[i - 1]$ 、目標金額は $amt$ です。各種類のコインは複数回選択でき、**目標金額を構成できるコインの組み合わせは何通りありますか**。以下の例を参照してください
$n$ 種類の硬貨が与えられ、$i$ 番目の硬貨の額面は $coins[i - 1]$ 、目標金額は $amt$ です。各硬貨は繰り返し選択できるとして、**目標金額を作る硬貨の組合せ数**を求めてください。例を以下の図に示します
![コイン交換問題IIの例データ](unbounded_knapsack_problem.assets/coin_change_ii_example.png)
![硬貨交換問題 II のサンプルデータ](unbounded_knapsack_problem.assets/coin_change_ii_example.png)
### 動的プログラミングアプローチ
### 動的計画法の考え方
の問題と比較して、この問題の目は組み合わせの数を決定することであるため、部分問題は次のようになります:**最初の $i$ 種類のコインを使用して金額 $a$ を構成できる組み合わせの数**。$dp$ テーブルはサイズ $(n+1) \times (amt + 1)$ の次元行列のまま残ります。
問と比べて、本問の目は組合せ数を求めることです。そのため、部分問題は **先頭 $i$ 種類の硬貨で金額 $a$ を作れる組合せ数** になります。一方、$dp$ テーブルは引き続きサイズ $(n+1) \times (amt + 1)$ の 2 次元行列す。
現在の状態の組み合わせ数は、現在のコインを選択しない組み合わせと現在のコインを選択する組み合わせの合計です。状態遷移方程式は
現在の状態における組合せ数は、現在の硬貨を選ばない場合と選ぶ場合の 2 つの選択肢の組合せ数の和に等しくなります。状態遷移方程式は次のとおりです。
$$
dp[i, a] = dp[i-1, a] + dp[i, a - coins[i-1]]
$$
目標金額が $0$ の場合、目標金額を構成するのにコインは必要ないため、最初の列のすべての $dp[i, 0]$ $1$ に初期化されるべきです。コインがない場合、任意の金額 >0 を構成することは不可能であるため、最初の行のすべての $dp[0, a]$ は $0$ に設定されるべきです。
目標金額が $0$ のときは、どの硬貨も選ばなくても目標金額を作れるため、先頭列のすべての $dp[i, 0]$ $1$ に初期化します。硬貨がないときは、任意の $>0$ の目標金額を作れないため、先頭行のすべての $dp[0, a]$ は $0$ になります。
### コード実装
@@ -200,7 +200,7 @@ $$
### 空間最適化
空間最適化アプローチは同じで、コインの次元を削除するだけです
空間最適化の方法も同様で、硬貨の次元を削除するだけです
```src
[file]{coin_change_ii}-[class]{}-[func]{coin_change_ii_dp_comp}