背包问题

【动态规划】01背包问题_两种解法

…衆ロ難τιáo~ 提交于 2019-12-03 00:30:15
问题描述 0-1背包问题:给定 \(n\) 种物品和一背包。物品i的重量是 \(w_i\) ,其价值为 \(v_i\) ,背包的容量为 \(C\) 。问:应该如何选择装入背包的物品,使得装人背包中物品的总价值最大? 在选择装人背包的物品时,对每种物品 \(i\) 只有两种选择,即装人背包或不装入背包。不能将物品 \(i\) 装入背包多次,也不能只装入部分的物品 \(i\) 。因此,该问题称为 0-1背包问题 。 此问题的形式化描述是,给定 \(C>0\) , \(w_i>0\) , \(v_i>0\) , \(1≤i≤n\) ,要求找出 \(n\) 元0-1向量 \((x_1,x_2,\cdots,x_n), x_i\in\{0,1\},1 \leq i \leq n\) ,使得 \(\sum_{i=1}^{n} w_ix_i \leq C\) ,而且 \(\sum_{i=1}^{n} v_ix_i\) 达到最大。因此,0-1背包问题是一个特殊的整数规划问题。 \[max\sum_{i=1}^{n} v_ix_i\] \[\left\{\begin{matrix} \sum_{i=1}^{n} w_ix_i \leq C & \\ x_i\in\{0,1\}, & 1 \leq i \leq n \end{matrix}\right.\] 最优子结构性质 0

贪心算法解背包问题

匿名 (未验证) 提交于 2019-12-03 00:26:01
问题描述: 给定 n 个物品和一个容量为 C 的背包,请 给出物品装入背包的方案,使得背包中物品的总价值 M 最大,并 满足: 每个物品 I 的重量为 w i ,价值为 v i 。 每个物品可拆分,背包中物品的总重量不能超过容量 C 。 实验要求: 程序实现要求: 1 )先写排序算法 Rank() ,再写贪心算法 Greedy() 。 2 )两个步骤需要单独定义在程序里,不写在主函数里。 贪心算法解背包问题的基本步骤: 1 )计算每种物品单位重量的价值 V i / W i 2 )依贪心选择策略,将尽可能多的 单位重量价值最高 的物品装入背包。 3 )若将这种物品全部装入背包后,背包内的物品总重量未超过 C ,则选择单位重量价值次高的物品并尽可能多地装入背包。 4 #include<stdio.h> #define N 100 int v[N];//价值 int w[N];//重量 float fw[N];//防止比例小数,转换重量用 int record[N];//记录排序后每个数字原来位置,从0开始,对应vw数组 int C;//给出背包容量 int n;//物品个数 int M=0;//背包容量为C时最大价值 int SurplusC;//剩余背包重量 void swap(int *x,int *y){//交换函数 int temp; temp=*x; *x=*y; *y

动态规划-完全背包系列

匿名 (未验证) 提交于 2019-12-03 00:22:01
完全背包与01背包的区别在于,01背包中所有物品要么选要不不选,完全背包是所有物品可以选任意次。完全背包与01背包很相似,可以将完全背包转换成01背包,也可以找到其状态转移方程。 1.完全背包 2.完全背包变形题-最小乘车费用 3.完全背包变形题-货币系统 1.完全背包 问题描述:有n件物品和一个容量为m的背包,每件物品都有无限件可用,第i件物品的体积为w[i],价值是v[i],求解将哪些物品放入背包可使这些物品的价值总和最大并且不超过背包容量。 说明:完全背包问题和01背包问题相似,可以将其改造成01背包问题。 方法一 :改造状态转移方程:f(n,m) = max{k*v[i]+f(i-1,j-k*w[i])},其中k=0….j/w[i] 这样需要使用三层for循环,时间复杂度高,不推荐。 **方法二:**f(n,m) = max{f(n-1,m),f(n,m-w[n])+v[n]} package com.zd.dp.complete; import java.util.ArrayList; /** * 完全背包问题 * 有n个物品和容量为m的背包,每件物品有无限件,求最价值最大 * */ public class Main { public static void main (String[] args){ int n = 4 ; int [] weight = { 2 ,

动态规划与0-1背包问题解析

匿名 (未验证) 提交于 2019-12-03 00:19:01
动态规划,作为程序员面试过程中几乎是必考的题目类型,在实际生产应用中也广泛使用。0-1背包问题作为最经典的算法之一,也衍生了很多其他的题目(如找零钱、爬楼梯等leetcode题目)。本人在复习之余,将总结下来的算法常识得以分享: (一)什么是动态规划 作为运筹学的一个分支,动态规划(DP)最早是用于求解决策过程最优化的问题被提出,利用各阶段dp变量之间的关系,逐个求解,最终求得全局最优解的过程。再设计DP算法时,需确认原问题与子问题的解状态,每个状态下的DP值、边界状态值,以及状态转移方程。 此外,不同于分治策略,DP 划分的子问题是有重叠的,解过程中对于重叠的部分只要求解一次,记录下结果,其他子问题直接使用即可,减少了重复计算过程。 另外,DP在求解一个问题最优解的时候,不是固定的计算合并某些子问题的解,而是根据各子问题的解的情况选择其中最优的。即第i个状态的DP值dp[i]可能前i-1个状态( dp[1]、dp[2]、・・・・・・、dp[i-1] )都相关。 (2)子问题重叠性质:先计算子问题的解,再由子问题的解去构造问题的解(由于子问题存在重叠,把子问题解记录下来为下一步使用)。 (二)0-1背包求解思路 ④、确定状态转移方程,如何从一个或多个已知状态求出另一个未知状态的值。(递推型) (三)算法设计   初始状态为dp[0][0]~ dp[0][ V]和 dp[0][0]~

hduoj FATE(二维完全背包)

匿名 (未验证) 提交于 2019-12-03 00:18:01
FATE Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 17607 Accepted Submission(s): 8263 Problem Description 最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务。久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级。现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度。当忍耐度降到0或者0以下时,xhd就不会玩这游戏。xhd还说了他最多只杀s只怪。请问他能升掉这最后一级吗? Input 输入数据有多组,对于每组数据第一行输入n,m,k,s(0 < n,m,k,s < 100)四个正整数。分别表示还需的经验值,保留的忍耐度,怪的种数和最多的杀怪数。接下来输入k行数据。每行数据输入两个正整数a,b(0 < a,b < 20);分别表示杀掉一只这种怪xhd会得到的经验值和会减掉的忍耐度。(每种怪都有无数个) Output 输出升完这级还能保留的最大忍耐度,如果无法升完这级输出-1。 Sample Input 10 10 1 10 1 1 10 10 1 9

背包问题c++动态规划方式

匿名 (未验证) 提交于 2019-12-03 00:16:01
#include <iostream> using namespace std; int weight[5] = {5,2,4,8,6}; int len[5] = {2,4,3,1,7}; int num = 5; int space = 15; int main() { int max_weight[15] = {0}; for(uint32_t i=0; i<num;i++) { for(uint32_t j=space; j>len[i]; j--) { if (max_weight[j-len[i]] + weight[i] > max_weight[j]) { max_weight[j] = max_weight[j-len[i]] + weight[i]; } } for(uint32_t j=0; j<space; j++) { cout<<max_weight[j]<<" "; } cout<<endl; } cout<<max_weight[14]<<endl; return 0; }   结果 0 0 0 5 5 5 5 5 5 5 5 5 5 5 5 0 0 0 5 5 5 5 7 7 7 7 7 7 7 7 0 0 0 5 5 5 9 9 9 9 11 11 11 11 11 0 0 8 8 13 13 13 17 17 17 17 19 19 19 19

01背包问题

匿名 (未验证) 提交于 2019-12-03 00:13:02
01背包问题 问题描述 一个旅行者有一个最多能装m公斤的背包,现在有n中物品,每件的重量分别是W1、W2、……、Wn,每件物品的价值分别为C1、C2、……、Cn, 需要将物品放入背包中,要怎么样放才能保证背包中物品的总价值最大?  假设前n个物品,总承重为j,物品的重量为w,其最大价值为v[n,j]。  在背包的总承重不变的前提下,一个物品是否放入背包中直接影响到后面的物品是否能放入到背包中,即一个物品很重同事物品价值又很低时,若装入背包中直接导致其他更多的物品无法放入背包中,从而使得背包中的最大总价值变低。   当背包的承重为0,或者不将物品放入背包时,背包中的最大总价值均为0,即v[n,0]=v[0,n]=0。   放入当前物品n超过背包的最大承重时,则无法将该物品放入背包中,即v[n,j]=v[n-1,j]。  放入当前物品n不超过背包的最大承重时,则当前物品放入背包时的最大价值为vn+v[n-1,j-wn],不放入背包时的最大价值为v[n-1,j],因此对于当前物品是否放入背包中所能获得的最大价值为v[n,j]=max{ v[n-1,j],vn+v[n-1,j-wn] }。 状态转化方程为: public static int [][] dp_bag( int m , int n , int w [], int p []){ int [][] c = new int [ n

背包问题

匿名 (未验证) 提交于 2019-12-03 00:11:01
背包问题 1、0-1背包(f[v]表示容量为v的背包的最大价值) 题目: 有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。 特点:每个物品只可取一次 不放第i 件物品的价值:f[i-1][v],问题转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v]; 放入第i 件物品的价值:f[i-1][v-c[i]]+v[i], 问题转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中” 主体代码: for i=1..N //第几件物品 初始化: 若要求恰好装满背包:将f[0]初始化为0,其余f[1…N]初始化为-∞,此时只有f[0]的初始值是有意义的,其余的背包都无意义 若不要求装满,值需要得到最大价值的背包:将f[0…N]都初始化为0 2、完全背包 题目描述: 有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。 特点:物品可以重复取 对于每种物品策略:取0次、 取1次、2次… 代码描述: for i=1..N 3、多重背包 题目描述: 有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]

分组背包问题

匿名 (未验证) 提交于 2019-12-03 00:09:02
有 N 组物品和一个容量是 V 的背包。 每组物品有若干个,同一组内的物品最多只能选一个。 每件物品的体积是 vij,价值是 wij,其中 i 是组号,j 是组内编号。 求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。 输出最大价值。 输入格式 第一行有两个整数 N,V,用空格隔开,分别表示物品组数和背包容量。 接下来有 N 组数据: 每组数据第一行有一个整数 Si,表示第 i 个物品组的物品数量; 每组数据接下来有 Si 行,每行有两个整数 vij,wij,用空格隔开,分别表示第 i 个物品组的第 j 个物品的体积和价值; 输出格式 输出一个整数,表示最大价值。 数据范围 0<N,V≤100 0<Si≤100 0<vij,wij≤100 输入样例 3 5 2 1 2 2 4 1 3 4 1 4 5 输出样例: 8 #include<bits/stdc++.h> using namespace std; #define maxn 1000010 typedef long long ll; int a[maxn],b[maxn],dp[maxn]; int main(){ memset(dp,0,sizeof(dp)); int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ int num; scanf("%d"

[算法模版]树形背包

匿名 (未验证) 提交于 2019-12-03 00:05:01
树形01背包和普通背包不同点在于物品之间有相互的依赖关系。选取儿子物品的必要条件是选取了所有他的祖先。 我们考虑使用 dp[i][j] 代表第 i 个点的子树内,花费了 j 个容量能得到的最大权值。 伪代码: for ( int i = 1 ; i <= son ; i ++){ //枚举所有儿子 dfs ( son [ i ]); //先处理儿子 for ( int j1 = m ; j1 >= 0 ; j1 --){ //枚举当前点用掉了多少容量(正着枚举会变成完全背包) for ( int j2 = 0 ; j2 <= j1 ; j2 ++){ //枚举这个儿子分配多少 dp [ i ][ j1 ]= max ( dp [ i ][ j1 ], dp [ i ][ j1 - j2 ]+ dp [ son [ i ]][ j2 ]); //更新状态 } } } 显然,复杂度是 \(O(n*m^2)\) 的。 当物品的体积全部为1时,我们可以把它优化到 \(O(n^2)\) 的复杂度。 来自lsj爷爷的代码: 乍一看根原来的没什么不同,但是需要注意,对于每一对点,都只会在他们的LCA被枚举到一次。可以自己想想为什么。 复杂度 \(n^2\) 。 例题 有一种方法可以把它优化到 \(n*m\) 的复杂度。 咕咕咕 树上背包的上下界优化 【算法讲堂】【电子科技大学】【ACM