背包问题
1 原生代码便于理解
2 石墨文档笔记
https://shimo.im/docs/KpdJ99pyJrkcgtgR
/* 建议B站搜视频学习
动态二维数组网页:
https://misakasister.github.io/Online_0-1_Knapsack/index.html
网页github源码:
https://github.com/Misakasister/Online_0-1_Knapsack/blob/master/index.html
我的石墨文档课件笔记:https://shimo.im/docs/KpdJ99pyJrkcgtgR
w[i]:表示第i个物品的重量
B[k - 1] [c - w[ i ] ] :表示只考虑前(k-1)个物品,在c-w[i]的承重下所能获得的最大价值.
此时说明背包减去了C[j]的重量,所以后面要加v[i],获得了第i个物品的价值. 可以理解为从上
一个状态一直留着空间给第i个物品.看看加上第i个物品的价值能不能超过不花费w[i]的容量,只有钱i-1个物品的最大价值
花不起就还是和k-1个物品的最大价值的最大价值相同
*/
#include<stdio.h>
#define N 6 //1-5个物品
#define W 21 //背包20的容量
int B[N][W] = {0};
int w[6] = {0,2,3,4,5,9}; //每一个物品的重量
int v[6] = {0,3,4,5,8,10}; //对应物品的价值
void knapsack(){
int k,c;
for(k = 1;k < N;k++){
for(c = 1; c < W;c++){
if(w[k] > c){ //当前背包容量小于当前物品重量
B[k][c] = B[k-1][c]; //最大价值与前N-1个保持不变
}
else{
int value1 = B[k-1][c-w[k]] + v[k];
int value2 = B[k-1][c];
if(value1 > value2){
B[k][c] = value1;
}
else{
B[k][c] = value2;
}
}
}
}
}
int main(){
knapsack();
printf("%d\n",B[5][20]);
}
利用一维数组滚动遍历优化代码
/*
int value1 = B[k-1][c-w[k]] + v[k];
int value2 = B[k-1][c];
发现每次都是在二维数组同一行(k-1)比较,说明可以使用一维数组优化空间
为了防止数据覆盖,记录最大价值的一维dp数组从后往前赋值
*/
#include<stdio.h>
#define N 5 //1-5个物品
#define W 20 //背包有20的容量
int dp[1001];
int w[6] = {0,2,3,4,5,9}; //每一个物品的重量
int v[6] = {0,3,4,5,8,10}; //对应物品的价值
int main(){
int max(int ,int);
int k,c; //k表示前k个,c表示当前的容量
for(k = 1;k <= N;k++){
for(c = W; c >= 0;c--){
if(c < w[k]) break; //因为是从后往前递归,容量是由大到小,大容量小于物品体积 直接结束。
dp[c] = max(dp[c],dp[ c-w[k] ] + v[k]);
}
}
printf("%d\n",dp[W]);
return 0;
}
int max(int a,int b){
int temp;
temp = a > b ? a : b;
return temp;
}