解题思路
第一问就是简单的01背包问题,这里不多赘述,有不明白的自己去找资料吧。
关键是第二问,问背包恰好装满的情况下,最多能装价值多少的物品。这里的恰好装满是关键。
为了避免不必要的空间浪费,我这里使用map进行处理,其中map的任意一个键值对[key, val]表示正好装满体积为key的空间的最大价值为val。
map的底层是红黑树,它本身是一个有序的容器,增删改查的时间复杂度都在O(logn)。
我们让map的key从大到小排列,这样方便后续的状态转移。具体做法是:
1、初始化map[0] = 0,即体积为0时价值为0。
2、对于每一件物品的v和w,我们遍历整个map的所有键值对[key, val],若key + v <= V,有状态转移方程
map[key + v] = max(map[key + v], val + w)。
下面贴出完整代码。
#include <iostream> #include <map> #include <vector> using namespace std; int main() { int n, V, v, w; cin >> n >> V; vector<int> dp(V + 1, 0); map<int, int, greater<>> mp; mp[0] = 0; for (int i = 0; i < n; ++i) { cin >> v >> w; for (int j = V; j >= v; --j) { dp[j] = max(dp[j], dp[j - v] + w); } for (auto &[key, val] : mp) { if (key + v <= V) mp[key + v] = max(mp[key + v], val + w); } } cout << dp[V] << endl; cout << mp[V]; }