背包问题

二维费用的背包问题

被刻印的时光 ゝ 提交于 2020-02-01 20:02:53
有 N 件物品和一个容量是 V 的背包,背包能承受的最大重量是 M。 每件物品只能用一次。体积是 vi,重量是 mi,价值是 wi。 求解将哪些物品装入背包,可使物品总体积不超过背包容量,总重量不超过背包可承受的最大重量,且价值总和最大。 输出最大价值。 输入格式 第一行两个整数,N,V,M,用空格隔开,分别表示物品件数、背包容积和背包可承受的最大重量。 接下来有 N 行,每行三个整数 vi,mi,wi,用空格隔开,分别表示第 i 件物品的体积、重量和价值。 输出格式 输出一个整数,表示最大价值。 数据范围 0<N≤1000 0<V,M≤100 0<vi,mi≤100 0<wi≤1000 输入样例 4 5 6 1 2 3 2 4 4 3 4 5 4 5 6 输出样例: 8 完整代码: #include <bits/stdc++.h> #define int long long using namespace std; int n,v,m; int f[110][110];//f[i][j]表示体积为i,重量为j时的最大价值 signed main() { ios::sync_with_stdio(false); cin.tie(0); cin>>n>>v>>m; for(int i=0;i<n;i++){ int vi,wi,val; cin>>vi>>wi>>val; for

[专题七] 动态规划

痴心易碎 提交于 2020-02-01 12:48:34
01背包 完全背包 多重背包 分组背包 混合背包 对于物品而言只能选择1个或者0个两种情况 对于物品而言可以无限制选取,也可以不选 对于物品而言最多能够选择从s[i]个,同样也可不选 一些物品捆绑在一起,每一组物品中只能选择其中的一个物品 有些物品可以选择1,有些物品可以选择无数个,有些物品只能选择是s[i]个.即:01背包+完全背包+多重背包. 滚动数组 滚动数组 滚动数组 滚动数组 滚动数组 二进制优化或者单调队列优化 其中多重背包部分参考多重背包优化 0 - 1 背包问题 有 N N 件物品和一个容量是 V V 的背包。每件物品只能使用一次。 第 i i 件物品的体积是 v i vi,价值是 w i wi。 求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。 输出最大价值。 /* 特点:每个物品仅能使用一次 f[i][j]:前i个物品,背包容量为j的情况下的最优解 1)当前背包容量不够,为前i-1个物品最优解:j<w[i] f[i][j] = f[i-1][j] 2)当前背包容量够,判断选与不选第i个物品 选:f[i][j] = f[i-1][j-w[i]] + v[i] 不选:f[i][j] = f[i-1][j] */ // 二维表示法 int n, m; int v[N], w[N]; //v为体积 w为价值 int f[N][N]; int

背包问题

北城以北 提交于 2020-01-31 05:59:09
Backpack 给定N个物品,重量分别为正整数A0,A1,…,AN-1 一个背包最大承重是正整数M 最多能带走多重的物品 例子: 输入: 4个物品,重量为2,3,5,7 背包最大承重是11 输出: 10 01背包问题 # include <cstdio> # include <algorithm> using namespace std ; int d [ 1000 ] , w [ 1000 ] , n , m ; int main ( ) { scanf ( "%d%d" , & n , & m ) ; for ( int i = 0 ; i < n ; i ++ ) { scanf ( "%d" , & w [ i ] ) ; } for ( int i = 0 ; i < n ; i ++ ) { for ( int j = m ; j >= w [ i ] ; j -- ) { d [ j ] = max ( d [ j ] , d [ j - w [ i ] ] + w [ i ] ) ; } } // for(int i = 0; i <= m; i++) { // printf("%d ", d[i]); // } printf ( "%d" , d [ m ] ) ; return 0 ; } 2、 给定N个正整数:A0,A1,…,AN-1 一个正整数target

AcWing 12 背包问题求具体方案

僤鯓⒐⒋嵵緔 提交于 2020-01-31 04:22:55
题目描述: 有 N 件物品和一个容量是 V的背包。每件物品只能使用一次。 第 i件物品的体积是 vi,价值是 wi。 求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。 输出 字典序最小的方案 。这里的字典序是指:所选物品的编号所构成的序列。物品的编号范围是 1…N。 输入格式 第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。 接下来有 N行,每行两个整数 vi,wi,用空格隔开,分别表示第 i件物品的体积和价值。 输出格式 输出一行,包含若干个用空格隔开的整数,表示最优解中所选物品的编号序列,且该编号序列的字典序最小。 物品编号范围是 1…N。 数据范围 0<N,V≤1000 0<vi,wi≤1000 输入样例 4 5 1 2 2 4 3 4 4 6 输出样例: 1 4 分析: 对于一般的01背包问题,f[i][j]表示前i个物品中选出体积不超过j的物品的最大价值。f[i][j] = max(f[i-1][j],f[i-1][j-v]+w)。如果只是求其中的任一具体方案,可以根据f[n][m]是否等于f[n-1][m-v[n]]+w[n],等于则说明可以选第n个物品,然后继续根据f[m-1][m-v[n]]是否可以由前一层的状态f[i-2][m-v[n]-v[n-1]]转移而来继续判断是否可以选择第n-1个物品。但是题目要求字典序最小的方案

动态规划 背包问题

荒凉一梦 提交于 2020-01-30 07:34:07
详细解读背包问题 0/1背包问题: 有N件物品和一个容量为V的背包,第i件物品消耗的容量为Ci,价值为Wi,求解放入哪些物品使背包中总价值最大。 仔细想想,这里每个物品只有一个,对于每个物品而言,只有两种选择,装入或不装入,装入记为1,不装入为0,我们不能将物品进行分割,比如只拿半个是不允许的。这就是这个问题被称为0/1背包问题的原因。 在选择的过程中,我们每做出一种选择,都会将一种情况分裂成两种,最终我们会得到一张决策图: 定义函数KS(i,j) 代表当前背包剩余容量为j时,前i个物品最佳组合所对应的价值 对于第i个物品,有两种可能: 背包剩余的容量不足以装下第i个物品,此时KS(i,j)等于KS(i-1,j) 背包剩余容量可以装下第i个物品,此时需要进行判断,因为装下该物品不一定会使最终结果是最优组合,此时我们在两中情况中选择最优情况如果不装该物品,则价值为KS(i-1,j),装下该物品的话,价值为KS(i-1,j-wight[i])+value[i] 状态转移方程 f[i][v]=max{ f[i-1][v],f[i-1][v-w[i]]+val[i] },考录问题“将前i个物品放入背包中的最大价值”,可能存在两种情况,即存在第i个物品和不存在第i个物品,我们只需在其中取最优解即可。 对于这个问题的子问题,这里有必要详细说明一下。原问题是,将n件物品放入容量为c的背包

背包真假专题

余生颓废 提交于 2020-01-29 23:01:08
目录 前言 CF3B Lorry 题目 分析 代码 前言 传统意义上的背包是有一些众所周知的定义和判断性质的 有 \(n\) 件物品,每件物品有价值、体积、数量(1个、无限、规定数量)等属性(一般就是这三个),彼此可能存在依赖或排斥,现在要把它们尽量放入一个容积为 \(m\) 的背包里,问获得的最大价值 然后主要分为01背包、完全背包、多重背包等(比如还有混合背包(前三个总和)、二维费用背包、分组背包等) 01背包:时间复杂度 \(O(nm)\) ,空间复杂度 \(O(m)\) 完全背包:时间复杂度 \(O(nm)\) ,空间复杂度 \(O(m)\) 多重背包:时间复杂度 \(O(nm\sum cnt)\) ,空间复杂度 \(O(m)\) ,二进制优化时间复杂度变成 \(O(nm\log \sum cnt)\) 多重背包单调队列优化:时间复杂度 \(O(nm)\) ,空间复杂度 \(O(m)\) 不管怎样,背包问题始终无法脱离时间复杂度 \(O(nm)\) ,空间复杂度 \(O(m)\) 的框框吧(至少我现在是这么认为的) 那么对于 \(n,m\) 超过 \(10000\) 很有可能并不是背包。 而且注意背包问题是不能够贪心的,除了部分背包(可以塞一部分当然按性价比排序,它也不属于背包) 然后一旦题目的模型可以转换成背包,可以暗暗庆幸——又是道思维题(然而我连模型转换都不会

【DP_背包专辑】【from zeroclock's blog】

只愿长相守 提交于 2020-01-29 03:38:19
本文转自:zeroclock的博客 这短时间看了论文《背包九讲》,看到背包问题解法中的优美之处也看到背包问题在现实中的应用,总结出一句话:背包问题值得一看。 背包问题可以概括为这样的模型:有若干种选择,每种选择有一定的代价和价值,做某些选择会得到特定的状态,问我们在约定的条件下怎么得到特定的状态?这里的状态可以是代价和或者价值和或者由其他这两者组合而来的状态。这类问题需要枚举每种状态,但是可以通过动态规划减少枚举的次数,提高效率,主要思想是每次都利用前面得到的状态进行转移得到当前的状态。这类问题很少能用贪心的,首先,贪心很难证明策略是否正确,其次贪心必定使得枚举量大量减少,会导致结果错误。 个人认为背包九讲中的很多模型本质都是两种模型:01背包模型、完全背包模型。大家可以把这两种模型理解透彻,然后再看其他模型,这样必定事半功倍。 看《背包九讲》的过程中开了一个专题,大概26道题目,主要是Hdu和Poj的题目,题目有难有易,这次的专辑主要讲解这些题目,还有一些Uva的简单背包问题也会加入到这个专辑中。本专辑都只列举基本思路,如果大家想看详细思路或者代码请去我博客中查找,大部分题目我都有写解题报告。 一、01背包问题 (先枚举物品,再逆序枚举容量) 1、Hdu 2602 Bone Collector 非常常规的01背包问题,用一维和二维数组都可以做,一维快相当多。 1 //二维0

Leetcode 题解 - 动态规划

ぃ、小莉子 提交于 2020-01-28 11:13:07
递归和动态规划都是将原问题拆成多个子问题然后求解,他们之间最本质的区别是,动态规划保存了子问题的解,避免重复计算。 斐波那契数列 Leetcode-70. 爬楼梯 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数。 示例 1: 输入: 2 输出: 2 解释: 有两种方法可以爬到楼顶。 1. 1 阶 + 1 阶 2. 2 阶 示例 2: 输入: 3 输出: 3 解释: 有三种方法可以爬到楼顶。 1. 1 阶 + 1 阶 + 1 阶 2. 1 阶 + 2 阶 3. 2 阶 + 1 阶 解法: Java 定义一个数组 dp 存储上楼梯的方法数(为了方便讨论,数组下标从 1 开始),dp[i] 表示走到第 i 个楼梯的方法数目。 第 i 个楼梯可以从第 i-1 和 i-2 个楼梯再走一步到达,走到第 i 个楼梯的方法数为走到第 i-1 和第 i-2 个楼梯的方法数之和。 考虑到 dp[i] 只与 dp[i - 1] 和 dp[i - 2] 有关,因此可以只用两个变量来存储 dp[i - 1] 和 dp[i - 2],使得原来的 O(N) 空间复杂度优化为 O(1) 复杂度。 class Solution { public int climbStairs ( int n ) { if ( n

多重背包问题的二进制优化的数学基础

陌路散爱 提交于 2020-01-28 08:57:29
多重背包问题是背包问题中的一类,具体是指,给定一个背包的容积 V V V ,给定一列物品,以及其体积向量 w [ i ] w[i] w [ i ] ,价值向量 v [ i ] v[i] v [ i ] 和个数向量 s [ i ] s[i] s [ i ] ,也就是物品 i i i 的价值是 v [ i ] v[i] v [ i ] ,有 s [ i ] s[i] s [ i ] 个,占用的体积是 w [ i ] w[i] w [ i ] ,问在如何在保证背包装得下的情况下,最大可能装的物品的总价值是多少。 在多重背包问题中有一种经典的二进制优化,可以把枚举物品数量的过程从 O ( s ) O(s) O ( s ) 变成 O ( log ⁡ s ) O(\log s) O ( lo g s ) ,也把多重背包问题转化成了0-1背包问题。此文的目的是给其中的数学基础给予证明。 命题:给定一个正整数 x x x ,和一个可重集合 S = { 1 , 2 , 4 , 8 , . . . , 2 k , r } S=\{1,2,4,8,...,2^k,r\} S = { 1 , 2 , 4 , 8 , . . . , 2 k , r } ,其中 2 k + 1 − 1 ≤ x < 2 k + 2 2^{k+1}-1 \le x<2^{k+2} 2 k + 1 − 1 ≤ x < 2 k +

01背包

↘锁芯ラ 提交于 2020-01-27 08:05:57
问题描述 已知 : 有一个容量为 V 的背包和 N 件物品,第 i 件物品的重量是 weight[i] ,价值是 cost[i] 。 问 : 在不超过背包容量的情况下,最多能获得多少价值。 01 背包的特点 : 每种物品只有一件,可以选择放或者不放 1子问题:f[i][v] 表示前i件物品放到一个容量为v的背包中可以获得最大价值 2.状态转移方程:f[i][v] = max(f[i - 1][v],f[i - 1][v - weight[i]] + cost[i]) 1) 如果第 i 件物品不放入背包中,那么问题就转换为:将前 i - 1 件物品放到容量为 v 的背包中,带来的收益 f[i - 1][v] 2) 如果第 i 件物品能放入背包中,那么问题就转换为:将前 i - 1 件物品放到容量为 v - weight[i] 的背包中,带来的收益 f[i - 1][v - weight[i]] + cost[i] 代码【01背包二维数组实现】 #include <iostream> #include <cstring> #include <cstdio> using namespace std; int N,V; //物品个数 ,背包最大容量 int weight[100],value[100];//物品重量 ,物品价值 int f[100][100] = {{0}}; /* 目标