演算法-動態規劃-完全揹包

Frank23發表於2024-08-29

0. 動態規劃五部曲:

  1. 確定dp陣列(dp table)以及下標的含義
  2. 確定遞推公式
  3. dp陣列如何初始化
  4. 確定遍歷順序
  5. 舉例推導dp陣列

img

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]);
    }
}

相關文章