01背包、完全背包、多重背包(模板+优化)

1 篇文章 0 订阅
1 篇文章 0 订阅

此文章不提供具体解题思路,仅提供模板。

 

01背包

你有一个容量为W的背包,n个物品,物品的重量为weight[i],价值为value[i],物品只有一件。求背包能装的最大价值。

dp[n + 1][W + 1]的二维数组初始化为0,dp[i][j]:i表示前i件物品,j表示当前的背包容量,则dp[i][j]表示i,j状态下背包的价值,只是当前最优,不过随着更新,dp[i][j]会变成全局最优。

public int solve(int[] weight, int[] value, int W, int n) {
		int[][] dp = new int[n + 1][W + 1]; //已经全部初始化为0
		for (int i = 0; i < n; ++i) {
			for (int j = 0; j <= W; ++j) {
				if (j > weight[i]) {
					dp[i + 1][j] = Math.max(dp[i][j], dp[i][j - weight[i]] + value[i]);
				} else {
					dp[i +1][j] = dp[i][j];
				}
			}
		}
		return dp[n][W];
	}

空间优化: O(n^2) -> O(n)

public int solve(int[] weight, int[] value, int W, int n) {
		int[] dp = new int[W + 1]; //初始化为0
		for (int i = 0; i < n; ++i) {
			for (int j = W; j >= weight[i]; --j) {//从后往前更新,因为后面的需要用到前面的数据
				dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
			}
		}
		return dp[W];
}

 


完全背包

你有一个容量为w的背包,n个物品,物品的重量为W[i],价值为V[i],物品数量无限。求背包能装的最大价值。

// 完全背包
	public static int solve(int[] W, int[] V, int w) {
		//已经初始化全部为0
		// 第一维表示前几个物体 dp[0][x]表示前0个物品,即没有
		// 第二维表示重量
		int[][] dp = new int[W.length + 1][w + 1];
		for (int i = 0; i < W.length; ++i) {//物品循环
			for (int j = 0; j <= w; ++j) {//重量循环
				for (int k = 0; k * W[i] <= j; ++k) {//数量循环
					// k = 0的目的主要是第一次让dp[i + 1][j] = dp[i][j]
					// 其后是为了比较,所以第一个dp的i要加1
					dp[i + 1][j] = Math.max(dp[i + 1][j], dp[i][j - k * W[i]] + k * V[i]);
				}
			}
		}
		return dp[W.length][w];
	}

优化:时间复杂度O(n^3) -> O(n^2)  空间复杂度O(n^2) -> O(n)

// 完全背包 时间、空间优化
	public static int solve(int[] W, int[] V, int w) {
		int[] dp = new int[w + 1];
		for (int i = 0; i < W.length; ++i) {
			for(int j = W[i]; j <= w; ++j) {
				if (j >= W[i]) {
					dp[j] = Math.max(dp[j], dp[j - W[i]] + V[i]);
				}
			}
		}
		return dp[w];
	}

 


多重背包

你有一个容量为w的背包,n个物品,物品的重量为W[i],价值为V[i],物品数量为C[i]。求背包能装的最大价值。

//第一、三层循环为01背包,第二层循环思想类似完全背包的优化

public static int getAnswer(int[] W, int[] V, int[] C, int n) {
		int[] dp = new int[n + 1];
		for (int i = 0; i < W.length; ++i) {
			for (int k = 1; k <= C[i]; ++k) {
				for (int j = n; j >= W[i]; --j) {
					dp[j] = Math.max(dp[j], dp[j - W[i]] + V[i]);
				}
			}
		}
		return dp[n];
	}

二进制优化

public static int getAnswer1(int[] W, int[] V, int[] C, int n) {
		int[] dp = new int[n + 1];
		for (int i = 0; i < W.length; ++i) {
			for (int k = 1; C[i] > 0; k <<= 1) {
				if (k > C[i]) k = C[i];
				C[i] -= k;
				for (int j = n; j >= W[i] *k; --j) {
					dp[j] = Math.max(dp[j], dp[j - k * W[i]] + k * V[i]);
				}
			}
		}
		return dp[n];
	}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值