0. 動態規劃五部曲:
- 確定dp陣列(dp table)以及下標的含義
- 確定遞推公式
- dp陣列如何初始化
- 確定遍歷順序
- 舉例推導dp陣列
1. 完全揹包問題
完全揹包問題中,每個物品都有無數個
,可以重複選擇
。
- 二維dp陣列
int[][] dp = new int[n][totalWeight+1]; // 初始化第一行 for(int j = weight[0]; j<=totalWeight; ++j) { dp[0][j] = value[0] * (j/weight[0]); } for(int i = 1; i<n; ++i) { for(int j = 0; j<=totalWeight; ++j) { if(j < weight[i]) dp[i][j] = dp[i-1][j]; else dp[i][j] = Math.max(dp[i-1][j], dp[i][j-weight[i]]+value[i]); } }
- 一維dp陣列:
順序遍歷
,允許同種物品被重複選擇。int[] dp = new int[totalWeight+1]; for(int i = 0; i<n; ++i) { for(int j = weight[i]; j<=totalWeight; ++j) { dp[j] = Math.max(dp[j], dp[j-weight[i]] + value[i]); } }
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int totalWeight = scanner.nextInt();
int[] weight = new int[n];
int[] value = new int[n];
for(int i = 0; i<n; ++i) {
weight[i] = scanner.nextInt();
value[i] = scanner.nextInt();
}
int[] dp = new int[totalWeight+1];
for(int i = 0; i<n; ++i) {
// 順序遍歷,同一個物品可以重複選
for(int j = weight[i]; j<=totalWeight; ++j) {
dp[j] = Math.max(dp[j], dp[j-weight[i]]+value[i]);
}
}
System.out.println(dp[totalWeight]);
}
}