背包问题

HZNU-ACM寒假集训Day7小结

大城市里の小女人 提交于 2020-02-04 20:45:01
背包问题 01背包 状态:f(i,j) 表示只能装前i个物品的情况下,容量为j的背包所能达到的最大总价值 状态转移方程: f(i,j)=max(f(i-1,j),f(i-1,j-w[i])+v[i]) 核心代码(滚动数组) 由于我们使用一维数组存储,则在求两个子问题时没有直接取出那么方便了,因为第i次循环可能覆盖第i-1次循环的结果 “相反,如果在执行第 i 次循环时,背包容量按照0..V的顺序遍历一遍,来检测第 i 件物品是否能放。此时在执行第i次循环 且 背包容量为v时,此时的f[v]存储的是 f[i - 1][v] ,但是,此时f[v-weight[i]]存储的是f[i][v-weight[i]]。 因为,v > v - weight[i],第i次循环中,执行背包容量为v时,容量为v - weight[i]的背包已经计算过,即f[v - weight[i]]中存储的是f[i][v - weight[i]]。即,对于01背包,按照增序枚举背包容量是不对的。” for (int i = 1; i <= n; i++) { for (int j = m; j >= w[i]; j--) { f[j] = max(f[j], f[j - w[i]] + v[i]); } } 但是,增序枚举会达到什么效果:它会 重复的装入某个物体 , 而且尽可能的多使价值增大 完全背包问题

0-1背包问题

我们两清 提交于 2020-02-04 19:06:49
0-1背包问题 问题描述:有个容量为m的背包和n∈[1, 100]个物品,每个物品的重量为w[i]∈[1, 100],价格为p[i]∈[1, 100],问如何装入物品,使得在不超过背包容量的情况下,使得装下的物品的价格最大? 这题有三种解法,咱们先介绍动态规划的解法。 构造一个一维数组f[10005],f[i]表示背包容量为i时,背包里的物品价格的最大值 于是我们有递推式f[i] = max( f[i], f[i - w] + p); 动态规划 采用自顶而下的遍历 #include <bits/stdc++.h> using namespace std; int f[10005]; int main() { int w[105], p[105], n, m; while(~scanf("%d%d", &n, &m) && n) { memset(w, 0, sizeof(w)); memset(p, 0, sizeof(p)); memset(f, 0, sizeof(f)); for(int i = 0;i < n; ++i) scanf("%d%d", &w[i], &p[i]); for(int i = 0;i < n; ++i) for(int j = m;j >= w[i]; --j) f[j] = max(f[j], f[j - w[i]] + p[i]);

【贪心算法】背包问题

心已入冬 提交于 2020-02-04 12:27:53
题目:有一个背包,背包容量是M=150。有7个物品,物品可以分割成任意大小。 要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。 物品 A B C D E F G 重量 35 30 60 50 40 10 25 价值 10 40 30 50 35 40 30 思路: 让你把物品一个个的往包里装,要求装入包中的物品总价值最大,要让总价值最大,就可以想到怎么 放一个个的物品 才能让总的价值最大,因此可以想到如下三种选择物品的方法, 即可能的局部最优解 : ①:每次都选择价值最高的往包里放。 ②:每次都选择重量最小的往包里放。 ③:每次都选择单位重量价值最高的往包里放。 找到可能的局部解以后,分析每一种解能不能合起来变成总体最优解,对以上三中局部解一一分析: ①:选择价值最高的,就会忽略了重量,若 M=50, 物品1: 重量:50,价值:40 物品2: 重量:20,价值30 物品3: 重量:30,价值30 显然,对于上述情况,该局部解行不通。 ②:选择重量最小的,就会忽略了价值,同①策略类似。 ③:该策略总是能让装入包中的物品总价值最大,所以该策略是正确的贪心策略。 注:(http://blog.csdn.net/a925907195/article/details/41314549 该篇博客说第三种情况在一下情况是错的, 物品:A B C 重量:28 20 10 价值:28

背包算法

喜欢而已 提交于 2020-02-04 12:27:08
被朋友要求帮忙写一个程序。主要核心是算法,归纳起来核心是背包算法。原来学的早忘了。上网搜吧。 背包算法(转贴) http://hi.baidu.com/wzra/blog/item/7827b1c353532654b319a811.html /**/ /* * * 背包问题 * 背包问题是计算机科学里的经典问题。在最简单的形式中,包括试图将不同重量的数据项放到 * 背包中.以使背包最后达到指定的总重量。不需要把所有的选项都放入背包中。 * 举例来说,假设想要背包精确地承重20磅,并且有5个可以选择放入的数据项,它们的重量 * 依次为11磅、8磅、7磅、6磅和5磅。对于选择放入的数据项数量不大时,人类很善于通过观察 * 就可以解决这个问题。于是大概可以计算出只有8磅、7磅和5磅的数据项加在一起和为20磅。 * 如果想要计算机来解决这个问题,就需要给计算机更详细的指令。算法如下: * 1.如果在这个过程中的任何时刻,选择的数据项的总和符合目标重量,工作就完成了。 * 2.从选择第一个数据项开始。剩余的数据项的加和必须符合背包的目标重量减去第一个数据 * 项的重量;这是一个新的目标重量。 * 3.逐个地试每种剩余数据顶组合的可能性。但是,注意并不需要去试所有的组合,因为只要 * 数据顶朗和大于目标重量的时候,就停止添加数据项。 * 4.如果设有组合合适的话,放弃第—‘个数据项

完全背包问题

廉价感情. 提交于 2020-02-04 10:31:05
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 5 using namespace std; 6 7 const int max_n = 100+2; 8 const int max_W = 10000+2; 9 10 int n,W; 11 int dp[max_n][max_W]; 12 // 定义如下: 13 // dp[i][j]:从前i个物品中,选出重量不超过j的物品 14 // dp[0][j]=0 15 // d[i][j]=? 16 // if(j<w[i]) dp[i][j]=dp[i-1][j] 17 // else dp[i][j]=max(dp[i-1][j],dp[i][j-w[i]] + v[i]) 18 int w[max_n],v[max_n]; 19 20 void solve() 21 { 22 memset(dp,-1,sizeof(dp)); 23 // dp[0][j] = 0 24 // 初始条件 25 for(int i=0;i<=n;++i) 26 { 27 dp[0][i]=0; 28 } 29 30 for(int i=1;i<=n;++i) 31 { 32 for(int j=0;j<=W;++j) 33 { 34 if(j<w[i]) 35 {

贪心算法----部分背包问题(java实现)

别说谁变了你拦得住时间么 提交于 2020-02-04 02:21:23
部分背包问题 给定 n 种物品和一个背包.物品 i 的重量是 Wi,其价值为 Vi,背包的容量为 C.在选择物品 i 装入背包时,可以选择物品 i 的一部分,1<= i <=n.问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大. 代码: import java.util.Scanner; public class BackPack { /* Sort 将物品按价值比从大到小排放在数组 */ void Sort(int n ,float []v,float w[]) { float temp1; float temp2; for (int i = 1; i <= n; i++) { for (int s = 1; s <= i; s++) { if (v[i] / w[i] > v[s] / w[s]) { temp1 = v[s]; temp2 = w[s]; v[s] = v[i]; w[s] = w[i]; v[i] = temp1; w[i] = temp2; } } } } void Knapsack (int n,float W,float v[],float w[],float x[],float v2[],float w2[]) { BackPack a = new BackPack(); a.Sort(n, v, w); int i, ad; for

算法题 背包问题-02-Proud Merchants

谁都会走 提交于 2020-02-03 06:54:07
Recently, iSea went to an ancient country. For such a long time, it was the most wealthy and powerful kingdom in the world. As a result, the people in this country are still very proud even if their nation hasn’t been so wealthy any more. The merchants were the most typical, each of them only sold exactly one item, the price was Pi, but they would refuse to make a trade with you if your money were less than Qi, and iSea evaluated every item a value Vi. If he had M units of money, what’s the maximum value iSea could get? Input There are several test cases in the input. Each test case begin with

算法题 背包问题-03-Bone Collector

不想你离开。 提交于 2020-02-03 03:35:49
Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave … The bone collector had a big bag with a volume of V ,and along his trip of collecting there are a lot of bones , obviously , different bone has different value and different volume, now given the each bone’s value along his trip , can you calculate out the maximum of the total value the bone collector can get ? Input The first line contain a integer T , the number of cases. Followed by T cases , each case three

完全背包

女生的网名这么多〃 提交于 2020-02-01 22:40:30
问题描述: 基本思路: 这个问题和 01背包 问题非常的相似,只是 01背包 问题要求了每个物品我们最多可以选一次(选和不选两种选择),但是完全背包问题只要容量够我们可以无限制的选 如果我们依然采取和 01背包 一样的状态的定义 dp[i][j] 代表 前 i 个物品 容量为 j 的时候的最大价值 那么状态转移方程也就出来了: dp[i][j] = max(dp[i][j],dp[i][j-k*v[i]]+w[i]); int dp[1010][1010]; int v[1010],w[1010]; int main() { int n,m; std::cin >> n >> m; for (int i = 1;i <= n;i++) { std::cin >> v[i] >> w[i]; } for (int i = 1;i <= n;i++) { for (int j = 0;j <= m;j++) {for (int k = 0;k * v[i] <= j;k++) { dp[i][j] = std::max(dp[i][j],dp[i-1][j-k*v[i]]+k*w[i]); } } } std::cout << dp[n][m] << std::endl; return 0; } 但是稍微分析一下这个算法的时间复杂度 和 空间复杂度都是比较高的 我们可以采取和之前

多重背包

浪子不回头ぞ 提交于 2020-02-01 22:21:27
题目大意: 这个问题和 01背包 问题很相似,我们也可以依然采取 01背包 的状态定义 dp[i][j] 代表前 i 个物品 容量为 j 的背包的最大价值 那么状态转移方程也就出来了: dp[i][j] = max(dp[i][j],dp[i-1][j-k*v[i]]+w[i]) (k 可以为 0,1,2,3...s[i]) int dp[110][110],v[110],w[110],s[110]; int main() { int n,m; cin >> n >> m; for (int i = 1;i <= n;i++) { cin >> v[i] >> w[i] >> s[i]; } for (int i = 1;i <= n;i++) { for (int j = 1;j <= m;j++) { for (int k = 0;k <= s[i];k++) { if (k * v[i] <= j) dp[i][j] = std::max(dp[i][j],dp[i-1][j-k*v[i]]+k*w[i]); } } } cout << dp[n][m] << endl; return 0; } 这种朴素的方法的时间复杂度 和 空间复杂度都很高,所以一般不采取 我们可以先采取和 01背包 一样的滚动数组的方式去优化一下 简单优化: 和 01背包 一样,我们也应该 从大往小更新