01背包问题
记录在此,以防忘记
-
01背包的问题是指每种物体只有一个,放或者不放。
-
例:有5个物品,标号为1-5,重量分别是[2,2,6,5,4],价值分别是[6,3,5,4,6],背包总承受为10。
-
转移方程为:
-
dp[j] = max(dp[j-w[i]]+v[i],dp[j]); 得到表格:
重量w | 价值v | 编号i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ||
2 | 6 | 1 | 0 | 0 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
2 | 3 | 2 | 0 | 0 | 6 | 6 | 9 | 9 | 9 | 9 | 9 | 9 | 9 |
6 | 5 | 3 | 0 | 0 | 6 | 6 | 9 | 9 | 9 | 9 | 11 | 11 | 14 |
5 | 4 | 4 | 0 | 0 | 6 | 6 | 9 | 9 | 9 | 10 | 11 | 13 | 14 |
4 | 6 | 5 | 0 | 0 | 6 | 6 | 9 | 9 | 12 | 12 | 15 | 15 | 15 |
public class 背包问题之01背包 {
public static void main(String[] args) {
int[] w = {0,2,2,6,5,4}; //此处采用0开头是方便计数
int[] v = {0,6,3,5,4,6};
int N = 5; //物品总数
int V = 10; //总承受量
int[][] dp = new int[N+1][V+1];
for (int i = 1; i <= N; i++) {
for (int j = 0; j <= V; j++) {
if(j >= w[i]){
dp[i][j] = Math.max(dp[i-1][j-w[i]]+v[i], dp[i-1][j]);
}else{
dp[i][j] = dp[i-1][j];
}
}
}
System.out.println(dp[5][10]);
}
}
以上此方法时间复杂度为o(NV),空间复杂度为o(NV),还方法空间复杂度还可优化为o(V)
将dp数组只开成一维数组
则转移方程可化简为:dp[j] = max(dp[j-ci]+wi,dp[j]);
核心代码为:
for(int i = 1;i <= N;i++){
for(int j = V;j >= w[i];j--){
dp[j] = Math.max(dp[j-w[i]]+v[i],dp[j]);
}
}