欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 社会 > 算法【分组背包】

算法【分组背包】

2025/2/2 0:20:42 来源:https://blog.csdn.net/W_O_Z/article/details/145371880  浏览:    关键词:算法【分组背包】

分组背包是指多个物品分组,每组只能取1件。每一组的物品都可能性展开就可以了。注意时间复杂度不会升阶,O(物品数量 * 背包容量)。

下面通过题目加深理解。

题目一

测试链接:通天之分组背包 - 洛谷

分析:这道题是分组背包的模板,对每个分组进行可能性的展开即不取这个分组和取这个分组的每一个能取的物品。下面代码采用记忆化搜索,严格位置依赖和空间压缩的解法不再赘述。代码如下。

#include <iostream>
#include <vector>
using namespace std;
int m, n;
int number_of_group = 0;
vector<vector<int>> group;
int data[1000][2];
int dp[100][1001];
int f(int groups, int weight){if(groups == number_of_group){return 0;}if(dp[groups][weight] != -1){return dp[groups][weight];}int ans = f(groups+1, weight);int nums = group[groups].size();for(int i = 0;i < nums;++i){if(weight - data[group[groups][i]][0] >= 0){ans = ans > f(groups+1, weight - data[group[groups][i]][0]) + data[group[groups][i]][1] ?ans : f(groups+1, weight - data[group[groups][i]][0]) + data[group[groups][i]][1];}}dp[groups][weight] = ans;return ans;
}
int main(void){int a_i, b_i, c_i;scanf("%d%d", &m, &n);vector<int> temp;for(int i = 0;i <= 99;++i){group.push_back(temp);}for(int i = 0;i < n;++i){scanf("%d%d%d", &a_i, &b_i, &c_i);data[i][0] = a_i;data[i][1] = b_i;group[c_i].push_back(i);number_of_group = number_of_group > c_i ?number_of_group : c_i;}++number_of_group;for(int i = 0;i <= number_of_group-1;++i){for(int j = 0;j <= m;++j){dp[i][j] = -1;}}printf("%d", f(0, m));return 0;
}

其中,f函数返回在从组数为groups的组开始,剩余重量为weight的情况下的最大值。

题目二

测试链接:2218. 从栈中取出 K 个硬币的最大面值和 - 力扣(LeetCode)

分析:对于这道题,可以将每个栈看为一个分组,对每个分组进行可能性的展开,也就是不取这个栈和取1次、2次、3次......直到剩余次数和栈的硬币数的最小值。代码采用记忆化搜索,改成严格位置依赖和空间压缩的解法不再赘述。代码如下。

class Solution {
public:int dp[1000][2001];int f(int index, int times, vector<vector<int>>& piles){if(index == piles.size()){return 0;}if(dp[index][times] != -1){return dp[index][times];}int ans = f(index+1, times, piles);int length = piles[index].size();int sum = 0;for(int i = 0;i < length && i+1 <= times;++i){sum += piles[index][i];ans = ans > f(index+1, times-i-1, piles) + sum ?ans : f(index+1, times-i-1, piles) + sum;}dp[index][times] = ans;return ans;}int maxValueOfCoins(vector<vector<int>>& piles, int k) {for(int i = 0;i < 1000;++i){for(int j = 0;j < 2001;++j){dp[i][j] = -1;}}return f(0, k, piles);}
};

其中,f方法返回在从下标index的栈开始取,剩余次数为times的情况下,得到的最大值。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com