[01 백팩 이론] 01 백팩 문제 dp[j]
n개의 아이템과 최대 w의 무게를 지닐 수 있는 배낭이 있습니다.
i번째 항목의 가중치는 가중치[i]이고, 얻은 값은 값[i]이다.
각 품목별로 품목이 1개뿐이므로 배낭에 어떤 품목을 넣어야 하는지 알아보고 품목의 총 가치가 가장 큽니다.
답변
동적 프로그래밍
-
dp 배열과 아래 첨자의 의미를 결정합니다
. 롤링 배열dp[j]
:j
용량이 의 배낭은 최대 값이 의 항목을 운반할 수 있습니다.dp[j]
-
의 용량을 가진 배낭이 운반할 수 있는 최대값이
dp[j]
되는 재귀 공식을 결정합니다 . 의 용량을 가진 배낭이 운반할 수 있는 최대값을 나타내는 것으로 추론 할 수 있습니다 . 용량에 아이템 가치를 더한 배낭을 나타냅니다 . (즉, 아이템을 넣은 후 용량이 의 배낭 의 가치는 다음과 같습니다. ) 두 가지 옵션이 있습니다:j
dp[j]
dp[j - weight[i]]
dp[j - weight[i]]
j - weight[i]
dp[j - weight[i]] + value[i]
j - 物品i重量
i
j
i
dp[j]
dp[j]
- 하나는 자체를 취하는 것인데,
dp[j]
이는 2차원 dp 배열과 동일합니다dp[i-1][j]
. 즉, 항목이 배치되지 않습니다i
(지난번과 동일). - 하나는 가져가는 것
dp[j - weight[i]] + value[i]
, 즉 물건을 넣어서i
최대값을 지정하는 것이고, 결국 최대값을 추구하는 것이다.
- 하나는 자체를 취하는 것인데,
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
- dp 배열을 초기화하는 방법
dp[j]
의미 : j
용량이 의 배낭의 경우 소지품의 값은 최대 입니다. dp[j]
먼저, dp[0]=0.
dp 배열을 도출할 때 가장 큰 값을 갖는 숫자를 취해야 합니다. 값이 질문에 주어진 값이 모두 양의 정수이면 첨자는 0이 아닙니다. 그냥 모두 0으로 초기화하면 됩니다. 즉, 다른 첨자의 값은 모두 0으로 초기화되므로 dp 배열이 최대값을 취할 수 있습니다. 초기 값으로 덮어쓰이는 대신 재귀 수식 프로세스 중에.
- 순회 순서를 결정합니다.
2차원 dp를 순회할 때 배낭 용량은 작은 것부터 큰 것입니다. 1차원 dp를 순회할 때 배낭 용량은 큰 것에서 작은 것입니다. 항목을 먼저
정방향으로 배치한 다음 역순으로 배낭에 담습니다. 역순 순회는 항목이i
한 번만 삽입되도록 하기 위한 것이며, 양순으로 순회하면 항목 0이 여러 번 추가됩니다.
for(int i = 0; i < weight.size(); i++) {
// 遍历物品
for(int j = bagWeight; j >= weight[i]; j--) {
// 遍历背包容量
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
}
}
- dp 배열을 추론하는 예를 들어보겠습니다(dp 배열 인쇄).
배낭의 최대 무게는 4입니다. 물건:
무게 | 값 | |
---|---|---|
항목 0 | 1 | 15 |
항목 1 | 삼 | 20 |
항목 2 | 4 | 30 |
public class Solution {
public static void main(String[] args) {
int[] weight = {
1, 3, 4};
int[] value = {
15, 20, 30};
int bagWight = 4;
testWeightBagProblem(weight, value, bagWight);
}
public static void testWeightBagProblem(int[] weight, int[] value, int bagWeight){
int wLen = weight.length;
//定义dp数组:dp[j]表示背包容量为 j 时,能获得的最大价值
int[] dp = new int[bagWeight + 1];
//遍历顺序:先遍历物品,再遍历背包容量(倒序)
for (int i = 0; i < wLen; i++){
for (int j = bagWeight; j >= weight[i]; j--){
dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
}
}
//打印dp数组
for (int j = 0; j <= bagWeight; j++){
System.out.print(dp[j] + " ");
}
}
}