1.0-1背包的朴素形式
0-1背包问题:给定编号为1,2...n的n个物品和一个容量为C的背包;每个物品的重量为$w_i$,每个物品的价值为$v_i$,求将物品装入背包后,背包能获得的最大价值。其状态转移方程为:
$$ dp[i][j] = egin{cases} max{dp[i-1][j],dp[i-1][j-w_i] + v_i} ,& {j ≥ w_i} \ dp[i-1][j] , & {j < w_i} end{cases} $$
其中dp[i][j]表示把编号为从1到i的i个物品放入容量为j的背包所得到的最大的价值。其实现代码如下:
#include<iostream> #include<unordered_map> #include<queue> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<sstream> #include<set> #include<map> #include<stack> #define MAX_NUM 100 using namespace std; /*0-1背包的朴素形式*/ int main() { int n,C;//n为物品的个数,C为背包的容量 int weight[MAX_NUM]; int val[MAX_NUM]; int dp[MAX_NUM][MAX_NUM]; cout<<"输入物品个数和背包容量:"<<endl; cin>>n>>C; cout<<"分别输入这"<<n<<"个物品的重量和价值:"<<endl; for(int i = 1; i <= n; i++) cin>>weight[i]>>val[i]; memset(dp,0,sizeof(dp));//初始化dp数组 for(int i = 1; i <= n; i++) for(int j = 1; j <= C; j++) //此处j的初值也可以为weight[i]开始,其实这样效率更高;不过为了便于理解才写成从1开始 { if(j < weight[i]) dp[i][j] = dp[i- 1][j]; else dp[i][j] = max(dp[i - 1][j],dp[i-1][j - weight[i]] + val[i]); } cout<<"背包的最大价值为:"<<dp[n][C]<<endl; }
这种朴素形式的0-1背包的算法的时间复杂度为O(n*C),空间复杂度也为O(n*C)。
2.对0-1背包进行优化
对0-1背包的优化主要体现在空间复杂度的优化上,时间复杂度无法再优化了。可以参考:https://blog.csdn.net/hearthougan/article/details/53869671 或者 https://blog.csdn.net/yoer77/article/details/70943462
或者 https://www.cnblogs.com/fengziwei/p/7750849.html 。
其实现代码如下:
#include<iostream> #include<unordered_map> #include<queue> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<sstream> #include<set> #include<map> #include<stack> #define MAX_NUM 100 using namespace std; /*0-1背包的优化形式*/ int main() { int n,C;//n为物品的个数,C为背包的容量 int weight[MAX_NUM]; int val[MAX_NUM]; int dp[MAX_NUM];//变成了一位数组 cout<<"输入物品个数和背包容量:"<<endl; cin>>n>>C; cout<<"分别输入这"<<n<<"个物品的重量和价值:"<<endl; for(int i = 1; i <= n; i++) cin>>weight[i]>>val[i]; memset(dp,0,sizeof(dp));//初始化dp数组 for(int i = 1; i <= n; i++) for(int j = C; j >= 1; j--) //此处j的初值变成了C,然后递减;与朴素形式调过来了;当然此处的中止条件也可为j >= weight[i] { if(j < weight[i]) dp[j] = dp[j]; else dp[j] = max(dp[j],dp[j - weight[i]] + val[i]); } cout<<"背包的最大价值为:"<<dp[C]<<endl; }
优化后的0-1背包算法,时间复杂度仍为O(n*C),空间复杂度变成了O(C)。