欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【算法】01背包问题

程序员文章站 2022-06-04 10:52:32
...

有n个重量和价值分别为wi,vi的物品。 从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中价值总和的最大值。

限制条件

1<= n <=100

1<=wi,vi<=100

1<=W<=10000

代码:

import java.util.Scanner;

public class Main {
    static int n,W;
    static int w[],v[];
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
        W = in.nextInt();
        w = new int[n];
        v = new int[n];
        for (int i = 0; i < n; i++) {
            w[i] = in.nextInt();
            v[i] = in.nextInt();
        }
        System.out.println(rec(0, W));

    }
    public static int rec(int i,int j){
        int res;
        if (i == n){
            res = 0;
        }else if (j < w[i]){
            res = rec(i+1, j);
        }else{
            res  = Math.max(rec(i+1, j),rec(i+1,j-w[i])+v[i] );
        }
        return  res;
    }
}

上面的代码会出现重复计算的问题,我们可以对其再进行优化,从而节省时间。
【算法】01背包问题

import java.util.Scanner;

public class Main {
    static int N,W;	//背包数量,目标重量
    static int w[],v[]; //重量,价值
    static int dp[][];	//记忆数组
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        N = in.nextInt();
        W = in.nextInt();
        w = new int[N];
        v = new int[N];
        dp = new int[N+1][W+1];
        for (int i = 0; i < N; i++) {
            w[i] = in.nextInt();
            v[i] = in.nextInt();
        }
        //对记忆数组初始化
        for (int i = 0; i <=N; i++) {
            for (int j = 0; j <=W; j++) {
                dp[i][j] = -1;
            }
        }
        System.out.println(rec(0, W));
    }
    public static int rec(int i,int j){
        //当记忆数组中有值,直接返回
        if (dp[i][j]>=0){
            return dp[i][j];
        }
        int res;
        if (i == N){
            res = 0;
        }else if (j < w[i]){
            res = rec(i+1, j);
        }else{
            res  = Math.max(rec(i+1, j), rec(i+1,j-w[i]) +v[i] );
        }
        //节点的值储存在记忆数组中
        return dp[i][j] = res;
    }
}

终极优化

import java.util.Scanner;

public class Main {
    static int N, W;
    static int w[], v[];
    static int dp[][];

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        N = in.nextInt();
        W = in.nextInt();
        w = new int[N];
        v = new int[N];
        dp = new int[N + 1][W + 1];
        for (int i = 0; i < N; i++) {
            w[i] = in.nextInt();
            v[i] = in.nextInt();
        }
        System.out.println(rec());
    }

    public static int rec() {
        for (int i = N - 1; i >= 0; i--) {
            for (int j = 0; j <= W; j++) {
                if (j < w[i]) {
                    dp[i][j] = dp[i + 1][j];
                } else {
                    dp[i][j] = Math.max(dp[i + 1][j], dp[i + 1][j - w[i]] + v[i]);
                }
            }
        }
        return dp[0][W];
    }
}