0-1背包问题

0-1背包问题_第1张图片

二维版:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	static int N = 1010;
	static int[][] dp = new int[N][N];  //dp[i][j] 只选前i件物品,体积 <= j的最优解
	static int[] w = new int[N];    //存储价值
	static int[] v = new int[N];    //存储体积
	static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	public static void main(String[] args) throws IOException{
		String[] init = in.readLine().split(" ");
		int n = Integer.parseInt(init[0]);
		int Vmax = Integer.parseInt(init[1]);
		
		for(int i = 1;i <= n;i ++) {
			init = in.readLine().split(" ");
			v[i] = Integer.parseInt(init[0]);
			w[i] = Integer.parseInt(init[1]);
		}
		
		for(int i = 1;i <= n;i ++) {
			for(int j = 1;j <= Vmax;j ++) {
				if (v[i] > j) {     //当前背包装不下.最优解就是上一层的数据
					dp[i][j] = dp[i - 1][j];
				} else {
				    //装得下的话,背包的价值会变成dp[i - 1][j - v[i]] + w[i]
				    // j - v[i] 体积下的最优解 + w[i] 不一定会胜过dp[i - 1][j]
					dp[i][j] = Math.max(dp[i-1][j], dp[i - 1][j - v[i]] + w[i]);
				}
			}
		}
		System.out.print(dp[n][Vmax]);
		in.close();
	}
}

f[i][j]:只从前i个物品全,总体积<=j的最优解。局部最优=>全局最优

0-1背包问题_第2张图片

e41d401a4c5045b4b33e1fd9902f44ae.png

0-1背包问题_第3张图片

a879dd06032d414c8eef5110fa1bd894.png

d2d86aa804a54262ab63fd293ce17c15.png

一维版

由模拟二维的过程可知,通过不断覆盖前一维的状态,只一维数组也能实现

并且,并不是一维里的所有数据都需要更新,所以可以更新二维起始下标

二维更改一维需要满足条件,在决策dp[i][j]时,要能够知道dp[i - 1][j - v[i]]的状态

要用的是一行的数据,不能用当前行的数据

0-1背包问题_第4张图片

如表格中在决策第二件物品(v=2)时,dp[2]计算时,会把2更新成4,dp[4]计算时,需要用到上一次的2,而不是被更新过的4。所以决策时,每次都要用到前面的数据,但前面的数据又不能被改过。所以可以从后往前,可以确保你要决策的数,只被决策一次。

 

import java.io.*;
public class Main
{
    static int N = 1010;
    static int V;
    static int n;
    static int[] f = new int[N];   //只选前i件物品,背包容量为j的最优解
    static int[] v = new int[N];    //存体积
    static int[] w = new int[N];    //存价值
    static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    public static void main(String[] args)throws IOException
    {
        String[] init = in.readLine().split(" ");
        n = Integer.parseInt(init[0]);
        V = Integer.parseInt(init[1]);
        for(int i = 1;i <= n;i++){
            String[] data = in.readLine().split(" "); 
                v[i] = Integer.parseInt(data[0]);
                w[i] = Integer.parseInt(data[1]);
        }
        
        for(int i = 1;i <= n;i++){  
            //从后往前决策, j < v[i] 的地方不需要更新,直接用上一次的数据
            for(int j = V;j >= v[i];j--){
            
                    f[j] = Math.max(f[j],f[j-v[i]]+w[i]);
                
            }
        }
        System.out.println(f[V]);
        in.close();
    }
}

 

 

 

你可能感兴趣的:(算法,算法,数据结构,java)