经典动规--01背包

问题描述给定n个物品,每个物品有一个重量w和价值v,你有一个能装m重量的背包,问怎么装使得所装价值最大,每个物品只有一个。

如:n = 3, m = 5, wi = {2,3,4}; vi = {3,5,7};   

结果返回最大价值为:8

首先来填一个表格-->

        

第一,如果背包容量比该物品重量小,要不起,此时的价值等于[i - 1][ j ]格中的价值。

第二,如果背包容量可以装下该物品,要的起,但是会存在装了之后不一定价值超过没装之前。所以要在要和不要之间取一个最大值,要的话就得从当前背包容量减去物品重量,再从剩下容量的那一列去找,再加上要拿的物品价值。

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

一定要记得初始化第一行,如果j>=w[i],dp[0][j] = v[0];否则的话就是要不起dp[0][j] = 0;

下面直接上代码:

public class _01_knapsack {

	private static int n = 3;//物品数量
	private static int m = 5;//背包容量
	private static int[] w = {2,3,4};
	private static int[] v = {3,5,7};
	
	public static void main(String[] args) {
		_01_knapsack tem = new _01_knapsack();
		int res = tem.dp();
		System.out.println(res);
	}

	public int dp(){
		int[][] dp = new int[n][m+1];
		//初始化第一行
		for(int j = 0;j <= m;j++){
			if(j >= w[0]){
				dp[0][j] = v[0];//要的起,背包价值更新,物品只有一个,背包容量再大,价值也不变
			}else{
				dp[0][j] = 0;//要不起,价值为0
			}
		}
		
		for(int i = 1;i < n;i++){
			for(int j = 0;j <= m;j++){
				if(j>=w[i]){
					int a = dp[i-1][j];
					int b = dp[i-1][j - w[i]] + v[i];
					dp[i][j] = Math.max(a, b);
				}else{
					dp[i][j] = dp[i - 1][j];
				}
			}
		}
		return dp[n-1][m];//表格右下角为最大价值
	}
}

猜你喜欢

转载自blog.csdn.net/Baobab_Tree/article/details/89487338