背包问题

背包问题总结

◇◆丶佛笑我妖孽 提交于 2019-12-30 00:43:35
刷到背包了,背包是一类问题,开 个总 结记录贴 1 01 背包问题 题意:有N 件物品和一个容量为V 的背包。放入第i 件物品耗费的费用是Ci,得到的价值是Wi。求解将哪些物品装入背包可使价值总和最大 思路: 用子问题定义状态:即f[i,v] 表示前i 件物品恰放入一个容量为v 的背包可以获得的最大价值。则其状态转移方程便是:               f[i,v]=max(f[i,v],f[i-1,v-ci]+wi) 伪代码 通过递减顺序V~0,我们可以在每个i循环完后得到最终的状态,即可以省略i 对于恰好装满背包,需要初始化为负无穷 对于只要求最大价值的,需要初始化为0 例题:poj 3624 1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 int dp[13500]; 7 int w[13500],v[13500]; 8 int main() 9 { 10 int n,W; 11 #ifndef ONLINE_JUDGE 12 freopen("1.in","r",stdin); 13 #endif 14 while(scanf("%d%d",&n,&W)!=EOF) 15 { 16 int i,j,k; 17

P1757 通天之分组背包

一世执手 提交于 2019-12-27 05:44:11
P1757 通天之分组背包 背包中的经典问题,我竟然不知道。 分组背包 就是每个物品有一个所属的小组,小组内的物品会冲突。 就是把01背包中的两个for换一下位置 01: for(i,1,kind) for(j,v,w[i]) 分组背包 for(j,v,w[i]) for(i,1,kind) 1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<algorithm> 5 #include<cmath> 6 #include<ctime> 7 #include<cstring> 8 #define inf 2147483647 9 #define For(i,a,b) for(register int i=a;i<=b;i++) 10 #define p(a) putchar(a) 11 #define g() getchar() 12 //by war 13 //2017.10.17 14 using namespace std; 15 int n,m,x,y,z; 16 struct bag 17 { 18 int cnt; 19 int v[1010]; 20 int w[1010]; 21 }a[110]; 22 int f[1010]; 23 bool b[110]; 24 int kind

算法作业

馋奶兔 提交于 2019-12-27 03:16:39
# include <bits/stdc++.h> using namespace std ; # define MAXN 911 # define Inf 0x3f3f3f3f struct MatrixDimension { int n , m ; ///表示矩阵是n*m维的 } Di [ MAXN ] ; void TheMain ( ) ; void print ( int * * a , int * * b , int n , int m , bool f ) ; void MatrixChainMain ( ) ; void MatrixChain ( MatrixDimension MD [ ] , int * * s , int * * bestnum , int n ) ; void print1 ( int * * s , int l , int r ) ; void LCSlengthMain ( ) ; void LCSlength ( int n , int m , char * s1 , char * s2 , int * * c , int * * b ) ; void print2 ( char * s1 , char * s2 , int nr , int mr , int * * c ) ; void KnapsackMain ( ) ;

动态规划算法------背包问题

末鹿安然 提交于 2019-12-27 02:26:04
1、动态规划与分治法的相似点:都是将待求问题分解成若干个子问题,先求解出这些子问题,然后从子问题的解得到原问题的解 不同点:适合用动态规划求解的问题,经分解得到的子问题一般不是互相独立的。 2、动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中可能有许多可行解,每一个解都对应一个值,希望找到具有最优值的解。 3、动态规划算法的有效性依赖于最优子结构 和 子问题重叠 最优子结构 指的是问题的最优解 包含了 其子问题的最优解,使得程序能以自底向上的方式递推地从子问题的最优解逐步 构造出 整个问题的最优解 子问题重叠 指的是对某些子问题重复求解多次,动态规划能存储这些解。 4、解决动态规划的问题的手段: 第一:递归:先自上到底 再 自底到上 优势:正着由大规模问题推向小规模问题,容易想 劣势:但是效率低。 第二:迭代递推: 直接自底向上 优势 效率高 劣势:不好想 5、写动态规划算法,最重要的是要找到动态规划递推式 0-1背包问题,如果有n个物品,它们的重量分别为w1,w2......wn,价值分别为v1,v2....vn,现有一个负重为k的背包,要求选择物品装入背包, 使背包中物体总价值最大。 1、背包的状态转换方程 f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ), f[i-1,j] }//前者表示放入第i件物品(如果超出重量价值为0)

动态规划--背包

懵懂的女人 提交于 2019-12-26 22:35:34
1. 01背包: 有 N 件物品和一个容量为 V 的背包。第 i 件物品的费用是 c[i],价值是 w[i]。求解将哪些物品装入背包可使价值总和最大。    对于这类问题我们我们定义f[i][j]表示在前i个物品中选总容量为j所能得到的最大价值为多少于是我们状态转移便是这样 f[i][j]=max(f[i][j],f[i-1][j-w[i]]+v[i]); int f[N][M]; void work() { memset(f,0,sizeof(f)); for(int i=1;i<=n;i++) for(int j=w[i];j<=m;j++) f[i][j]=max(f[i][j],f[i-1][j-w[i]]+v[i]); for(int i=1;i<=m;i++) ans=max(f[n][i],ans); printf("%d\n",ans); }   这样一来,我们的时间复杂度就是O(nm),空间复杂度为O(nm),但我们发现f[i]的值只与f[i-1]有关,此时我们可以用滚动数组来优化空间到O(m),为f[j]=max(f[j],[j-w[i]]+v[i]);此时我们的j就要倒序枚举,因为j只会从比它小的j那转移。 int f[M]; void work() { memset(f,0,sizeof(f)); for(int i=1;i<=n;i++) for(int

动态规划0—1背包问题

百般思念 提交于 2019-12-26 12:10:41
动态规划0-1背包问题 Ø 问题描写叙述: 给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应怎样选择装入背包的物品,使得装 入背包中物品的总价值最大? Ø 对于一种物品,要么装入背包,要么不装。所以对于一种物品的装入状态能够取0和1.我们设物品i的装入状态为xi,xi∈ (0,1),此问题称为0-11背包问题。 过程分析 数据:物品个数n=5,物品重量w[n]={0,2,2,6,5,4},物品价值V[n]={0,6,3,5,4,6}, (第0位,置为0,不參与计算,仅仅是便于与后面的下标进行统一,无特别用处,也可不这么处理。)总重量c=10. Ø背包的最大容量为10,那么在设置数组m大小时,能够设行列值为6和11,那么,对于m(i,j)就表示可选物品为i…n背包容量为j(总重量)时背包中所放物品的最大价值。 以下是自己写的源代码: #include<stdio.h> #include<stdlib.h> #include<iostream> #include<queue> #include<climits> #include<cstring> using namespace std; const int c = 10; //背包的容量 const int w[] = {0,2,2,6,5,4};//物品的重量,当中0号位置不使用 。 const int

POJ 1155 (树形DP+背包+优化)

久未见 提交于 2019-12-26 05:35:44
题目链接 : http://poj.org/problem?id=1155 题目大意 :电视台转播节目。对于每个根,其子结点可能是用户,也可能是中转站。但是用户肯定是叶子结点。传到中转站或是用户都要花钱,如果是用户,则还可以收钱。问在不亏本的前提下最多能有多少个用户看到节目。 解题思路 : 比较麻烦的树形背包。首先cost=1。 花的钱权在边,收的钱权在点,且是叶子结点。所以首先可以对叶子结点进行预处理。 用dp[i][j]表示在i点时传播j个用户(包含自身),则dp[n-m-1~n][1]=每个用户缴费。 这样在dfs的时候就可以专心处理边权问题。两个for循环这么写: for(f...j...cost) for(0...k...j) 则转移方程就是dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[t][k]-e[a].w); 这里之所以是f而不是f+1,是因为中转站不是用户,不需要cost。f+=dfs(t)。 对于如何知道在不亏本的情况下的最多用户,在dfs之后,从dp[1][m..0]开始找一个大于0的最大m值。 如果你熟悉传统的树形背包的话,就会发现这里不能每次都使用最大背包容量m循环了,不然会TLE,原因是这题m比较大,每次都从m开始不T就怪了。 所以必须采用这种cost=1时特殊的当前最大容量f。 #include "cstdio"

0-1背包问题 动态规划算法 C++

余生长醉 提交于 2019-12-25 16:35:11
简单的0-1背包问题,使用动态规划的算法。 # include <iostream> # include "stdio.h" # include "stdlib.h" using namespace std ; int m [ 10 ] [ 10 ] ; int p [ 10 ] ; //价值 int w [ 10 ] ; //重量 void backpack ( int n , int c ) { for ( int i = 0 ; i < 10 ; i ++ ) { m [ 0 ] [ i ] = 0 ; m [ i ] [ 0 ] = 0 ; } for ( int i = 1 ; i <= n ; i ++ ) { for ( int j = 1 ; j <= c ; j ++ ) { if ( j < w [ i ] ) m [ i ] [ j ] = m [ i - 1 ] [ j ] ; if ( j >= w [ i ] ) { if ( m [ i - 1 ] [ j ] >= m [ i - 1 ] [ j - w [ i ] ] + p [ i ] ) m [ i ] [ j ] = m [ i - 1 ] [ j ] ; else { m [ i ] [ j ] = m [ i - 1 ] [ j - w [ i ] ] + p [ i ] ; } } }

背包问题: HDU1114Piggy-Bank

时间秒杀一切 提交于 2019-12-25 09:52:29
Piggy-Bank Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 25691 Accepted Submission(s): 13023 Problem Description Before ACM can do anything, a budget must be prepared and the necessary financial support obtained. The main income for this action comes from Irreversibly Bound Money (IBM). The idea behind is simple. Whenever some ACM member has any small money, he takes all the coins and throws them into a piggy-bank. You know that this process is irreversible, the coins cannot be removed without breaking the pig. After a sufficiently long

动态规划之0-1背包问题

时光总嘲笑我的痴心妄想 提交于 2019-12-25 07:30:40
给定n个物品和一个背包,物品i的重量是wi,其价值是vi,背包的容量为w,及最大载重量不超过W,在限定的总重量W内,我们如何选择物品,才能使物品的总价值最大。 具体问题: 有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和? m(i,j)表示当前背包的容量为j,可选择的物品范围为i,i+1,i+2....n。所以背包问题的递推式如下 m(i,j)={max{ m(i+1,j) ,m(i+1,j-w[i])+v[i]}(wi<=j), m(i+1,j)(wi>j)};( 但看公式还是比较抽象的 ) 下面具体的分析 现在我们才去的分析方法是从左往右,从下往上。 首先动态规划过程的表如下 这张表是从下往上从左往右的分析 当i=5时表示当前只有e一个物体,j从1到10慢慢增加表示背包容量在不断的增大,当j<=3的时候,背包的当前容量是小于e的,所以此时不能将物品加入到背包当中。当j>=4的时候恰好只有一个e所以背包最大为6。 当i=1,j=8的时候m[2][8]=9(不加上a),当加上a之后之后m[i+1][j-w[i]]+v[i]=m[2][6]+v[1]= 9+6=15.根据前面的公式m[i][j]=m[1][8]=15/其他的分析也是一样的