C语言八大排序算法性能实测:10万随机数下快排与堆排序耗时对比
2026/7/13 7:58:21
背包问题(Knapsack Problem)是经典的动态规划问题之一:
给定一个容量有限的背包和若干物品,每个物品有体积(或重量)*和*价值,问如何选择物品使得总价值最大**。
根据每个物品可选次数不同,背包问题主要分为:
Wni个物品:w[i]v[i]目标:
👉 在不超过背包容量的前提下,使总价值最大。
令:
dp[j] = 容量为 j 时能获得的最大价值对于第i个物品:
dp[j] = max(dp[j], dp[j - w[i]] + v[i])⚠️关键点:j必须从大到小遍历,防止一个物品被选多次。
#include<bits/stdc++.h>usingnamespacestd;intmain(){intn,W;cin>>n>>W;vector<int>w(n),v(n);for(inti=0;i<n;i++){cin>>w[i]>>v[i];}vector<int>dp(W+1,0);for(inti=0;i<n;i++){for(intj=W;j>=w[i];j--){dp[j]=max(dp[j],dp[j-w[i]]+v[i]);}}cout<<dp[W]<<endl;return0;}与 0/1 背包类似,但:
每个物品可以选无限次
dp[j] = max(dp[j], dp[j - w[i]] + v[i])⚠️关键区别:j必须从小到大遍历,允许多次使用当前物品。
#include<bits/stdc++.h>usingnamespacestd;intmain(){intn,W;cin>>n>>W;vector<int>w(n),v(n);for(inti=0;i<n;i++){cin>>w[i]>>v[i];}vector<int>dp(W+1,0);for(inti=0;i<n;i++){for(intj=w[i];j<=W;j++){dp[j]=max(dp[j],dp[j-w[i]]+v[i]);}}cout<<dp[W]<<endl;return0;}k[i]次三重循环,时间复杂度高。
将k个物品拆成:
1, 2, 4, ..., 剩余然后转化为0/1 背包问题。
#include<bits/stdc++.h>usingnamespacestd;intmain(){intn,W;cin>>n>>W;vector<int>dp(W+1,0);for(inti=0;i<n;i++){intw,v,k;cin>>w>>v>>k;for(intc=1;k>0;c<<=1){intnum=min(c,k);k-=num;intweight=num*w;intvalue=num*v;for(intj=W;j>=weight;j--){dp[j]=max(dp[j],dp[j-weight]+value);}}}cout<<dp[W]<<endl;return0;}| 类型 | 每件物品 | j 遍历方向 | 本质 |
|---|---|---|---|
| 0/1 背包 | 最多 1 次 | 从大到小 | 防止重复选 |
| 完全背包 | 无限次 | 从小到大 | 允许重复 |
| 多重背包 | 有上限 | 转化为 0/1 | 二进制优化 |