01背包、有依赖的背包
01背包(模版)
给定一个正数 t,表示背包的容量
有 m 个货物,每个货物可以选择一次
每个货物有自己的体积 costs[i] 和价值 values[i]
返回在不超过总容量的情况下,怎么挑选货物能达到价值最大
返回最大的价值
| #include <iostream> |
| #include <vector> |
| |
| using namespace std; |
| |
| int bag(vector<int> &cost, vector<int> &value, int t, int n) { |
| |
| vector<vector<int>> dp(n + 1, vector<int>(t + 1)); |
| |
| fill(dp[0].begin(), dp[0].end(), 0); |
| for (int i = 1; i <= n; ++i) { |
| for (int j = 0; j <= t; ++j) { |
| |
| dp[i][j] = dp[i - 1][j]; |
| |
| if (j - cost[i] >= 0) |
| dp[i][j] = max(dp[i][j], dp[i - 1][j - cost[i]] + value[i]); |
| } |
| } |
| |
| return dp[n][t]; |
| } |
| |
| int main() { |
| |
| int t, n; |
| cin >> t >> n; |
| |
| vector<int> cost(n + 1); |
| vector<int> value(n + 1); |
| for (int i = 1; i <= n; ++i) |
| cin >> cost[i] >> value[i]; |
| cout << bag(cost, value, t, n); |
| } |
| #include <iostream> |
| #include <vector> |
| |
| using namespace std; |
| |
| int bag(vector<int> &cost, vector<int> &value, int t, int n) { |
| |
| vector<int> dp(t + 1, 0); |
| for (int i = 1; i <= n; ++i) |
| |
| |
| |
| |
| |
| for (int j = t; j - cost[i] >= 0; j--) |
| dp[j] = max(dp[j], dp[j - cost[i]] + value[i]); |
| |
| return dp[t]; |
| } |
| |
| int main() { |
| |
| int t, n; |
| cin >> t >> n; |
| |
| vector<int> cost(n + 1); |
| vector<int> value(n + 1); |
| for (int i = 1; i <= n; ++i) |
| cin >> cost[i] >> value[i]; |
| cout << bag(cost, value, t, n); |
| } |
| #include <iostream> |
| #include <vector> |
| |
| using namespace std; |
| |
| #define ll long long |
| |
| |
| ll bag(vector<int> &cost, vector<ll> &value, int x) { |
| int n = cost.size() - 1; |
| vector<ll> dp(x + 1, 0); |
| for (int i = 1; i <= n; ++i) |
| for (int j = x; j - cost[i] >= 0; j--) |
| dp[j] = max(dp[j], dp[j - cost[i]] + value[i]); |
| return dp[x]; |
| } |
| |
| int main() { |
| |
| int n, x; |
| cin >> n >> x; |
| |
| vector<int> cost(1); |
| |
| vector<ll> value(1); |
| |
| ll res = 0; |
| int before, now; |
| ll happy; |
| for (int i = 1; i <= n; ++i) { |
| cin >> before >> now >> happy; |
| int val = before - now - now; |
| if (val > 0) { |
| |
| x += val; |
| res += happy; |
| } else { |
| cost.emplace_back(-val); |
| value.emplace_back(happy); |
| } |
| } |
| cout << res + bag(cost, value, x); |
| } |
| #include <vector> |
| |
| using namespace std; |
| |
| class Solution { |
| public: |
| int res; |
| |
| |
| void recursive(vector<int> &nums, int target, int curIndex, int sum) { |
| if (curIndex == nums.size()) { |
| if (sum == target) res++; |
| return; |
| } |
| recursive(nums, target, curIndex + 1, sum + nums[curIndex]); |
| recursive(nums, target, curIndex + 1, sum - nums[curIndex]); |
| } |
| |
| int findTargetSumWays(vector<int> &nums, int target) { |
| res = 0; |
| recursive(nums, target, 0, 0); |
| return res; |
| } |
| }; |
| #include <vector> |
| |
| using namespace std; |
| |
| class Solution { |
| public: |
| int recursive(vector<int> &nums, int target, int curIndex, int sum) { |
| if (curIndex == nums.size()) |
| return sum == target ? 1 : 0; |
| return recursive(nums, target, curIndex + 1, sum + nums[curIndex]) |
| + recursive(nums, target, curIndex + 1, sum - nums[curIndex]); |
| } |
| |
| int findTargetSumWays(vector<int> &nums, int target) { |
| return recursive(nums, target, 0, 0); |
| } |
| }; |
| #include <iostream> |
| #include <vector> |
| #include <unordered_map> |
| |
| using namespace std; |
| |
| class Solution { |
| public: |
| unordered_map<int, unordered_map<int, int>> dp; |
| |
| |
| |
| |
| int recursive(vector<int> &nums, int target, int curIndex, int sum) { |
| if (curIndex == nums.size()) |
| return sum == target ? 1 : 0; |
| if (dp.find(curIndex) != dp.end() && dp[curIndex].find(sum) != dp[curIndex].end()) |
| return dp[curIndex][sum]; |
| int res = recursive(nums, target, curIndex + 1, sum + nums[curIndex]) |
| + recursive(nums, target, curIndex + 1, sum - nums[curIndex]); |
| dp[curIndex].emplace(sum, res); |
| return res; |
| } |
| |
| int findTargetSumWays(vector<int> &nums, int target) { |
| return recursive(nums, target, 0, 0); |
| } |
| }; |
| #include <vector> |
| |
| using namespace std; |
| |
| class Solution { |
| public: |
| |
| int findTargetSumWays(vector<int> &nums, int target) { |
| int s = 0; |
| for (const auto &item: nums) |
| s += item; |
| |
| if (target < -s || target > s) return 0; |
| int n = nums.size(); |
| int m = 2 * s + 1; |
| |
| |
| |
| vector<vector<int>> dp(n + 1, vector<int>(m)); |
| dp[n][target + s] = 1; |
| for (int i = n - 1; i >= 0; i--) { |
| for (int j = -s; j <= s; j++) { |
| if (j + nums[i] + s < m) |
| dp[i][j + s] = dp[i + 1][j + nums[i] + s]; |
| if (j - nums[i] + s >= 0) |
| dp[i][j + s] += dp[i + 1][j - nums[i] + s]; |
| } |
| } |
| return dp[0][s]; |
| } |
| }; |
| #include <vector> |
| |
| using namespace std; |
| |
| class Solution { |
| public: |
| |
| |
| |
| int subsets(vector<int> &nums, int t) { |
| if (t < 0) return 0; |
| vector<int> dp(t + 1, 0); |
| dp[0] = 1; |
| for (int num: nums) |
| for (int j = t; j - num >= 0; j--) |
| dp[j] += dp[j - num]; |
| return dp[t]; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| int findTargetSumWays(vector<int> &nums, int target) { |
| int sum = 0; |
| for (int num: nums) sum += num; |
| |
| if (target < -sum || sum < target || ((target & 1) ^ (sum & 1)) == 1) return 0; |
| return subsets(nums, (target + sum) >> 1); |
| } |
| }; |
| #include <vector> |
| |
| using namespace std; |
| |
| class Solution { |
| public: |
| |
| |
| int getNear(vector<int> &nums, int t) { |
| vector<int> dp(t + 1); |
| for (int num: nums) |
| for (int j = t; j - num >= 0; j--) |
| |
| dp[j] = max(dp[j], dp[j - num] + num); |
| return dp[t]; |
| } |
| |
| int lastStoneWeightII(vector<int> &stones) { |
| int sum = 0; |
| for (int num: stones) |
| sum += num; |
| |
| int near = getNear(stones, sum / 2); |
| return sum - near - near; |
| } |
| }; |
有依赖的背包(模版)
| #include <vector> |
| #include <iostream> |
| |
| using namespace std; |
| |
| int main() { |
| int n, m; |
| cin >> n >> m; |
| |
| vector<int> cost(m + 1); |
| |
| vector<int> value(m + 1); |
| |
| vector<bool> king(m + 1); |
| |
| vector<vector<int>> follows(m + 1); |
| |
| |
| for (int i = 1, v, p, q; i <= m; ++i) { |
| cin >> v >> p >> q; |
| cost[i] = v; |
| value[i] = v * p; |
| king[i] = q == 0; |
| if (q != 0) follows[q].emplace_back(i); |
| } |
| |
| |
| vector<vector<int>> dp(m + 1, vector<int>(n + 1)); |
| |
| int pre = 0; |
| for (int i = 1, fan1, fan2; i <= m; ++i) { |
| |
| if (!king[i]) continue; |
| for (int j = 0; j <= n; ++j) { |
| |
| dp[i][j] = dp[pre][j]; |
| |
| if (j - cost[i] >= 0) |
| dp[i][j] = max(dp[i][j], |
| dp[pre][j - cost[i]] + value[i]); |
| |
| |
| fan1 = follows[i].size() >= 1 ? follows[i][0] : -1; |
| fan2 = follows[i].size() >= 2 ? follows[i][1] : -1; |
| |
| if (fan1 != -1 && j - cost[i] - cost[fan1] >= 0) |
| dp[i][j] = max(dp[i][j], |
| dp[pre][j - cost[i] - cost[fan1]] + value[i] + value[fan1]); |
| |
| if (fan2 != -1 && j - cost[i] - cost[fan2] >= 0) |
| dp[i][j] = max(dp[i][j], |
| dp[pre][j - cost[i] - cost[fan2]] + value[i] + value[fan2]); |
| |
| if (fan1 != -1 && fan2 != -1 && j - cost[i] - cost[fan1] - cost[fan2] >= 0) |
| dp[i][j] = max(dp[i][j], |
| dp[pre][j - cost[i] - cost[fan1] - cost[fan2]] + value[i] + value[fan1] + value[fan2]); |
| } |
| pre = i; |
| } |
| cout << dp[pre][n]; |
| } |
| #include <vector> |
| #include <iostream> |
| |
| using namespace std; |
| |
| int main() { |
| |
| int n, m; |
| cin >> n >> m; |
| |
| vector<int> cost(m + 1); |
| |
| vector<int> value(m + 1); |
| |
| vector<bool> king(m + 1); |
| |
| vector<vector<int>> follows(m + 1); |
| |
| |
| for (int i = 1, v, p, q; i <= m; ++i) { |
| cin >> v >> p >> q; |
| cost[i] = v; |
| value[i] = v * p; |
| king[i] = q == 0; |
| if (q != 0) follows[q].emplace_back(i); |
| } |
| |
| |
| |
| vector<int> dp(n + 1, 0); |
| for (int i = 1, fan1, fan2; i <= m; ++i) { |
| |
| if (!king[i]) continue; |
| |
| for (int j = n; j - cost[i] >= 0; j--) { |
| |
| |
| dp[j] = max(dp[j], dp[j - cost[i]] + value[i]); |
| fan1 = follows[i].size() >= 1 ? follows[i][0] : -1; |
| fan2 = follows[i].size() >= 2 ? follows[i][1] : -1; |
| |
| if (fan1 != -1 && j - cost[i] - cost[fan1] >= 0) |
| dp[j] = max(dp[j], dp[j - cost[i] - cost[fan1]] + value[i] + value[fan1]); |
| |
| if (fan2 != -1 && j - cost[i] - cost[fan2] >= 0) |
| dp[j] = max(dp[j], dp[j - cost[i] - cost[fan2]] + value[i] + value[fan2]); |
| |
| if (fan1 != -1 && fan2 != -1 && j - cost[i] - cost[fan1] - cost[fan2] >= 0) |
| dp[j] = max(dp[j], dp[j - cost[i] - cost[fan1] - cost[fan2]] + value[i] + value[fan1] + value[fan2]); |
| } |
| } |
| cout << dp[n]; |
| } |
非负数组前k个最小的子序列累加和
非负数组前k个最小的子序列累加和
给定一个数组 nums,含有 n 个数字,都是非负数
给定一个正数 k,返回所有子序列中累加和最小的前 k 个累加和
子序列是包含空集的
1 <= n <= 10^5
1 <= nums[i] <= 10^6
1 <= k <= 10^5
注意这个数据量,用 01 背包的解法是不行的,时间复杂度太高了
| #include <iostream> |
| #include <vector> |
| #include <algorithm> |
| #include <queue> |
| #include <random> |
| |
| using namespace std; |
| |
| |
| |
| |
| |
| |
| |
| |
| class Solution { |
| public: |
| |
| vector<int> topKSum1(vector<int> &nums, int k) { |
| |
| vector<int> allSubsequences; |
| recursive(nums, 0, 0, allSubsequences); |
| sort(allSubsequences.begin(), allSubsequences.end()); |
| vector<int> res(k); |
| |
| for (int i = 0; i < k; i++) |
| res[i] = allSubsequences[i]; |
| return res; |
| } |
| |
| |
| void recursive(vector<int> &nums, int curIndex, int sum, vector<int> &res) { |
| if (curIndex == nums.size()) { |
| res.push_back(sum); |
| return; |
| } |
| |
| recursive(nums, curIndex + 1, sum, res); |
| |
| recursive(nums, curIndex + 1, sum + nums[curIndex], res); |
| } |
| |
| |
| vector<int> topKSum2(vector<int> &nums, int k) { |
| int sum = 0; |
| for (int num: nums) sum += num; |
| vector<int> dp(sum + 1, 0); |
| dp[0] = 1; |
| for (int num: nums) |
| |
| for (int j = sum; j - num >= 0; j--) |
| dp[j] += dp[j - num]; |
| vector<int> res(k); |
| int index = 0; |
| for (int j = 0; j <= sum && index < k; j++) |
| for (int i = 0; i < dp[j] && index < k; i++) |
| res[index++] = j; |
| return res; |
| } |
| |
| struct cmp { |
| bool operator()(pair<int, int> &p1, pair<int, int> &p2) { |
| return p1.second > p2.second; |
| } |
| }; |
| |
| |
| |
| vector<int> topKSum3(vector<int> &nums, int k) { |
| sort(nums.begin(), nums.end()); |
| |
| priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> heap; |
| heap.push({0, nums[0]}); |
| |
| vector<int> res(k); |
| res[0] = 0; |
| for (int i = 1; i < k; i++) { |
| pair<int, int> cur = heap.top(); |
| heap.pop(); |
| int right = cur.first; |
| int sum = cur.second; |
| |
| res[i] = sum; |
| if (right + 1 < nums.size()) { |
| |
| heap.push({right + 1, sum - nums[right] + nums[right + 1]}); |
| |
| heap.push({right + 1, sum + nums[right + 1]}); |
| } |
| } |
| return res; |
| } |
| |
| |
| vector<int> randomArray(int len, int value) { |
| vector<int> ans(len); |
| random_device rd; |
| mt19937 gen(rd()); |
| uniform_int_distribution<> dis(0, value); |
| for (int i = 0; i < len; i++) |
| ans[i] = dis(gen); |
| return ans; |
| } |
| |
| |
| bool equals(const vector<int> &ans1, const vector<int> &ans2) { |
| if (ans1.size() != ans2.size()) return false; |
| for (int i = 0; i < ans1.size(); i++) |
| if (ans1[i] != ans2[i]) |
| return false; |
| return true; |
| } |
| }; |
| |
| int main() { |
| Solution solution; |
| int n = 15; |
| int v = 40; |
| int testTime = 5000; |
| cout << "测试开始" << endl; |
| for (int i = 0; i < testTime; i++) { |
| int len = rand() % n + 1; |
| vector<int> nums = solution.randomArray(len, v); |
| int k = rand() % ((1 << len) - 1) + 1; |
| vector<int> ans1 = solution.topKSum1(nums, k); |
| vector<int> ans2 = solution.topKSum2(nums, k); |
| vector<int> ans3 = solution.topKSum3(nums, k); |
| if (!solution.equals(ans1, ans2) || !solution.equals(ans1, ans3)) |
| cout << "出错了!" << endl; |
| } |
| cout << "测试结束" << endl; |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步