DataStructures - 07:动态规划之0-1背包问题

1. 问题描述

在这里插入图片描述
在这里插入图片描述

2. 思路分析

二维动态规划的的状态转移方程为:

dp[i][j] = max(dp[i-1][j], dp[i-1][j-v[i]] + w[i])

(1) 果不装第 i件物品,问题就转化为“前 i−1 件物品放入容量为 j的背包中的最大价值”
(2) 装第i件物品,问题转化为“前 i−1 件物品放入剩下容量为 j−v[i] 的背包中的最大价值”

状态转移方程:定义f[i][j]:前i个物品,背包容量j下的最优解
1)当前背包容量不够(j < w[i]),为前i-1个物品最优解:f[i][j] = f[i-1][j]
2)当前背包容量够,判断选与不选第i个物品
	选:f[i][j] = f[i-1][j-w[i]] + v[i]
	不选:f[i][j] = f[i-1][j]

在这里插入图片描述

3、代码实现

import java.util.Scanner;

/**
 * 1)当前背包容量不够(j < w[i]),为前i-1个物品最优解:f[i][j] = f[i-1][j]
 * 2)当前背包容量够,判断选与不选第i个物品
 * 	    选:f[i][j] = f[i-1][j-w[i]] + v[i]
 * 	    不选:f[i][j] = f[i-1][j]
 */
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNext()){

            //获取物品的数量N
            int N = scanner.nextInt();
            //获取背包的容积V
            int V = scanner.nextInt();

            //创建数组,第i个元素表示第i个物品的体积
            int[] v = new int[N+1];
            //创建数组,第i个元素表示第i个物品的价值
            int[] w = new int[N+1];

            //v[i]和w[i]分别表示第i件物品的体积和价值
            for(int i=1;i<=N;i++){
                v[i] = scanner.nextInt();
                w[i] = scanner.nextInt();
            }

            /**
             * 定义一个二维数组:dp[N+1][V+1]
             * 这里之所以要N+1和V+1:
             *      1、第0行表示只能选择第0个物品的时候,即没有物品的时候
             *      2、第0列表示背包的体积为0的时候,即不能装任何东西的时候
             */
            int[][] dp = new int[N+1][V+1];
            /**
             * dp[i][j]:在只能选择前i个物品且背包容量为j的情况下,背包中物品的最大价值
             *
             * 1、当前背包容量不够(j < w[i]),为前i-1个物品最优解:dp[i][j] = dp[i-1][j]
             * 2、当前背包容量够,判断选与不选第i个物品
             *      1、选:dp[i][j] = dp[i-1][j-w[i]] + v[i]
             *      2、不选:dp[i][j] = dp[i-1][j]
             */
            for(int i = 1; i <= N; i++){
                for(int j = 1; j <= V; j++){
                    if(j >= v[i]){
                        //判断选与不选当前物品
                        dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-v[i]] + w[i]);
                    }else{
                        dp[i][j] = dp[i-1][j];
                    }
                }
            }
            System.out.println(dp[N][V]);
        }
    }
}

优化为一维数组:

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNext()){

            //获取物品的数量N
            int N = scanner.nextInt();
            //获取背包的容积V
            int V = scanner.nextInt();

            //创建数组,第i个元素表示第i个物品的体积
            int[] v = new int[N+1];
            //创建数组,第i个元素表示第i个物品的价值
            int[] w = new int[N+1];

            //v[i]和w[i]分别表示第i件物品的体积和价值
            for(int i=1;i<=N;i++){
                v[i] = scanner.nextInt();
                w[i] = scanner.nextInt();
            }

            int[] dp = new int[V+1];
	        for(int i = 1; i <= N; i++){
	            for(int j = V; j >= v[i]; j--){
	                dp[j] = Math.max(dp[j], dp[j-v[i]] + w[i]);
	            }
	        }
	        System.out.println(dp[V]);
        }
    }
}
发布了716 篇原创文章 · 获赞 130 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/qq_42764468/article/details/105418766
今日推荐