编辑代码

// 导入java.util包中的ArrayList和List类,用于动态数组和列表操作  
import java.util.ArrayList;  
import java.util.List;  
  
// 定义一个公共类KnapsackProblem,它包含一个内部类Fruit和主方法main  
public class KnapsackProblem {  
    // 定义一个内部类Fruit,用于表示背包中的物品  
    // Fruit类包含三个属性:name(名称)、weight(重量)和value(价值)  
    static class Fruit {  
        String name;  
        int weight;  
        int value;  
  
        // 构造函数,用于初始化Fruit对象的属性  
        public Fruit(String name, int weight, int value) {  
            this.name = name;  
            this.weight = weight;  
            this.value = value;  
        }  
    }  
  
    // 主方法,程序的入口点  
    public static void main(String[] args) {  
        // 创建一个Fruit对象数组fruits,包含四种水果及其重量和价值  
        Fruit[] fruits = {  
                new Fruit("苹果", 15, 300),  
                new Fruit("香蕉", 18, 180),  
                new Fruit("橘子", 10, 150),  
                new Fruit("猕猴桃", 9, 270)  
        };  
  
        // 定义背包的容量capacity为20  
        int capacity = 20;  
        // 定义水果的数量n为fruits数组的长度  
        int n = fruits.length;  
  
        // 定义一个二维数组dp,用于存储中间状态,其大小为(n+1) * (capacity+1)  
        int[][] dp = new int[n + 1][capacity + 1];  
  
        // 使用双重循环填充dp数组  
        // 外层循环遍历水果的数量i,内层循环遍历背包的容量j  
        for (int i = 1; i <= n; i++) { // 外层循环,i从1到n  
            for (int j = 1; j <= capacity; j++) { // 内层循环,j从1到capacity  
                // 如果当前水果的重量小于等于当前背包容量j,则有两种选择:放入或不放入背包  
                if (fruits[i - 1].weight <= j) { // 判断是否可以放入当前水果  
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - fruits[i - 1].weight] + fruits[i - 1].value); // 选择放入当前水果或不放当前水果中的较大值  
                } else { // 如果当前水果的重量大于当前背包容量j,则不能放入背包,直接继承前一个状态的值  
                    dp[i][j] = dp[i - 1][j]; // 继承前一个状态的值  
                }  
            }  
        }  
  
        // 获取在背包容量为capacity时能够获得的最大价值,并存储在变量maxValue中  
        int maxValue = dp[n][capacity]; // 获取最大价值  
        System.out.println("装水果的最大价值为:" + maxValue); // 输出最大价值  
  
        // 创建一个ArrayList列表来存储装水果的策略(即放入背包的水果名称)  
        List<String> strategy = new ArrayList<>(); // 初始化策略列表为空列表  
        int w = capacity; // w用于表示当前背包剩余容量,初始值为背包容量capacity  
        for (int i = n; i > 0 && maxValue > 0; i--) { // 从最后一个水果开始向前遍历,直到第一个水果或者最大价值为0为止  
            if (maxValue != dp[i - 1][w]) { // 如果当前水果放入背包后不能获得最大价值,则将其加入策略列表中,并更新剩余容量和最大价值  
                strategy.add(fruits[i - 1].name); // 将当前水果名称加入策略列表中  
                maxValue -= fruits[i - 1].value; // 从最大价值中减去当前水果的价值  
                w -= fruits[i - 1].weight; // 从剩余容量中减去当前水果的重量  
            }  
        }  
  
        // 输出装水果的策略(即放入背包的水果名称)列表,从后往前输出,因为最后加入策略列表的是最先 放入背包的水果。
       
        System.out.println("装水果的策略:");
        for (int i = strategy.size() - 1; i >= 0; i--) { // 从策略列表的最后一个元素开始向前遍历
        System.out.println(strategy.get(i)); // 输出当前策略列表中的水果名称
        }
    }
}