接地气的解释 01背包问题

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;
}
原创文章 36 获赞 8 访问量 2755

猜你喜欢

转载自blog.csdn.net/qq_41398619/article/details/105723988