由于砝码的种类数较少,每种砝码的数量也不大,可以使用“暴力”方法来枚举所有可能的重量。
首先,使用一个 map<int, int, greater<int>>(或其他合适的数据结构)记录当前可以到达的重量集合,初始时包含重量 0。
这里使用 greater 是因为方便我直接使用 auto 进行从大到小的遍历,如果从小到大就变成完全背包了
对于第 i 种砝码,数量为 x[i],其重量为 m[i]。我们将它能够产生的新重量全部加入现有集合中,即:在当前所有可行重量基础上,累加 m[i] 一次,直到累加 x[i] 次,得到所有新的可行重量。
每次生成的新重量,都要并入已有集合(即合并到 mp)中。
最终,mp 中记录了所有可以用砝码组合得到的重量(包括 0)。mp.size() 即为不同重量的总数
#include <bits/stdc++.h> using namespace std; #define int long long const int N = 2e5 + 5; int __t = 1, n, m, x; void solve() { cin >> n; map<int, int, greater<int>> mp; mp[0] = 1; vector<int> m(n), x(n); for (int i = 0; i < n; i++) cin >> m[i]; for (int i = 0; i < n; i++) cin >> x[i]; for (int i = 0; i < n; i++) for (int j = 1; j <= x[i]; j++) { map<int, int, greater<int>> dmp; for (auto [k, v] : mp) dmp[k + m[i]] = 1; for (auto [k, v] : dmp) mp[k] = 1; } cout << mp.size() << '\n'; return; } int32_t main() { #ifdef ONLINE_JUDGE ios::sync_with_stdio(false); cin.tie(0); #endif // cin >> __t; while (__t--) solve(); return 0; }