01背包问题 java完整输入输出代码

背包问题总结

1. 01背包问题

N N N 件物品和一个容量是 V V V的背包。每件物品只能使用一次。

i i i 件物品的体积是 v i v_i vi,价值是 w i w_i wi

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式

第一行两个整数 N , V N,V NV,用空格隔开,分别表示物品数量和背包容积。

接下来有 N N N 行,每行两个整数 v i , w i v_i,w_i vi,wi,用空格隔开,分别表示第 i i i件物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0 < N , V ≤ 10000 < N , V ≤ 1000 0<N,V≤10000<N,V≤1000 0<N,V10000<N,V1000
0 < v i , w i ≤ 10000 < v i , w i ≤ 1000 0<v_i,w_i≤10000<v_i,w_i≤1000 0<vi,wi10000<vi,wi1000

输入样例

4 5
1 2
2 4
3 4
4 5

输出样例:

8

分析过程:

  1. 定义 f ( i , j ) f(i,j) f(i,j)表示第 1 到 i 1到i 1i个物品(包含第 1 1 1个和第 i i i个物品)满足总体积不超过 j j j的方案价值量

  2. 那么 f ( i , j ) f(i,j) f(i,j)可以表示为两部分:

    • 第一部分:不包含第 i i i个物品的
    • 第二部分:包含第 i i i个物品的

    对于第一部分,我们可以看成是第 1 到 ( i − 1 ) 1到(i-1) 1i1个(包含第 1 1 1个和第 i − 1 i-1 i1个物品),那么就可以表示成为 f ( i − 1 , j ) f(i-1,j) f(i1,j)

    对于第二部分,我们可以看成是前面可以任选,但是后面也一定要携带上第 i i i个物品,因此可以看成是前面 i − 1 i-1 i1个物品,然后占用的体积是 j − v [ i ] j-v[i] jv[i],然后加上第 i i i件物品的价值量 w [ i ] w[i] w[i],如下列式子:

    f ( i − 1 , j − v [ i ] ) + w [ i ] f(i-1,j-v[i]) + w[i] f(i1,jv[i])+w[i]

    然后最终的最大值可以表示为

    f ( i , j ) = M a t h . m a x ( f ( i − 1 , j ) , f ( i − 1 , j − v [ i ] ) + w [ i ] ) f(i,j) = Math.max(f(i-1,j),f(i-1,j-v[i]) + w[i]) f(i,j)=Math.max(f(i1,j),f(i1,jv[i])+w[i])

    因此可以用二维的数组来表示这种状态。

    不过一般这种二维dp的我们可以将其优化成一维dp的,仔细观察上式,我们可以发现只需要记录不包含第 i i i个物体的最大价值量和记录包含第 i i i个物体的最大价值量,因此,可以考虑用一个

    f ( j ) = M a t h . m a x ( f ( j ) , f ( j − v [ i ] ) + w [ i ] ) f(j) = Math.max(f(j),f(j-v[i]) + w[i]) f(j)=Math.max(f(j),f(jv[i])+w[i])

    一维数组来表示。考虑到数组下标要有意义即大于0,因此我们需要保证 0 ≤ j − v [ i ] 0≤j-v[i] 0jv[i]

完整的Java代码如下:

import java.io.*;
import java.util.*;

public class Main {
    
    
    
    private static int n;
    private static int m;
    private static int[] v = new int[1010];
    private static int[] w = new int[1010];
    private static int[] f = new int[1010];
    
    public static void main(String[] args) throws IOException {
    
    
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
        
        String[] num = reader.readLine().split(" ");
        int n = Integer.parseInt(num[0]);
        int m = Integer.parseInt(num[1]);
        
        for (int i = 1; i <= n; i++) {
    
    
            String[] arr = reader.readLine().split(" ");
            v[i] = Integer.parseInt(arr[0]);
            w[i] = Integer.parseInt(arr[1]);
        }
        for (int i = 1; i <= n; i++) {
    
    
            for (int j = m; j >= v[i]; j--) {
    
    
                f[j] = Math.max(f[j],f[j - v[i]] + w[i]);
            }
        }
        writer.write(f[m] + "\n");
        writer.flush();
        writer.close();
        reader.close();
    }
    
}

Guess you like

Origin blog.csdn.net/qq_41688840/article/details/114242296