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

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

 

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];
	}
发布了10 篇原创文章 · 获赞 0 · 访问量 211

猜你喜欢

转载自blog.csdn.net/qq_41084438/article/details/104106254