01背包

贪心算法_01背包问题_Java实现

烈酒焚心 提交于 2020-03-23 20:30:52
原文地址: http://blog.csdn.net/ljmingcom304/article/details/50310789 本文出自:【梁敬明的博客】 1.贪心算法   什么是贪心算法?是指在对问题进行求解时,总是做出当前看来是最好的选择。也就是说,不从整体最优上加以考虑,所得出的结果仅仅是某种意义上的局部最优解。因此贪心算法不会对所有问题都能得到整体最优解,但对于很多问题能产生整体最优解或整体最优解的近似解。 2背包问题     一个旅行者有一个最多能装m公斤的背包,现在有n中物品,每件的重量分别是W1、W2、……、Wn,每件物品的价值分别为C1、C2、……、Cn, 需要将物品放入背包中,要怎么样放才能保证背包中物品的总价值最大? 3.算法分析     当遇到这样的问题,我们可以换一种角度去思考,假设在一个100m3的房子里面,现在要将房子装满,同时要保证放入的物品个数最多以及装入的东西最重,现在身边有铁球和棉花,请问大家是放铁球进去好呢还是放棉花进去好呢?显而易见,放入铁球进去是最优选择。但是原因是什么呢?很简单,就是因为铁球的密度较大,相同体积的铁球和棉花相比,铁球更重。   不过前提是放入第一个铁球时,铁球的体积V1小于等于100m3 ;放入第二个铁球时,铁球的体积V2 小于等于(100-V1)m3;……;放入第n个铁球时,铁球的体积小于等于(100- ∑n1Vn-1

P2340 奶牛会展

十年热恋 提交于 2020-02-21 11:33:58
  感觉这是一道挺好的dp。   拿到题第一眼,就看出来是一个01背包(显然每一个只能选择取或者不取),那么只要一个做体积,一个做价值,跑完取所有v>0状态中v + f [ v ] 的最大值就可以了。但是,与普通的01背包有一点不同。   第一,这道题的容积有负的,这导致了dp转移方向的变化。想想平时为什么01背包从大往小,因为我更新这个状态用到了体积小的状态,而物品只能放一遍,自然要保证这个状态的更新不可以用到已经被这个物品更新的状态)。但是当体积出现负的时候,那么这个状态的更新就会用到大的体积,所以就要反向枚举体积了,这个是很好理解的。   我写的时候遇到了一个小问题——就是在选的过程中,和允许是负的。这就难办了——因为模拟体积的是数组下标,体积可以是负的,但是数组下标……为了解决这个问题,我们可以使用数组偏移的方法,也就是说用一个大值代表0,保证最小的数的绝对值小于这个代表0的数,最后结算的时候减去这个数就行了。   有个细节问题:就是如果这个体积是负的,反向枚举是从开始(我第一遍写的时候顺手就写了 v [ i ] ),以及上限是很大值 + v [ i ] ,因为我们要保证,我们的 j - v [ i ] 必须是在初始化范围内啊,也就是说,我们用来转移的状态必须合法。   注意这几个细节,这道题就很简单了。   下面是代码: #include<cstdio> #include

Acwing1020_潜水员01背包+思维

故事扮演 提交于 2020-02-14 23:13:16
题目链接:https://www.acwing.com/problem/content/description/1022/ 首先这道题目和普通的01背包看起来不一样,因为一般的01背包通常是闲置容量然后求价值的最大数值,而这道题目则是让我们需要满足2个一定的价值然后去选择最小的花费,价值可以超过预计的价值。 这里我直接开了三维,下面是解释: f[i, j, k]:表示在1 - i这些罐子里面选,然后满足氧气j,氮气k的最小花费。 状态转移方程: 不选第i个罐子, 那么f[i, j, k] = f[i - 1, j, k];但是注意这里需要加限制条件,因为我们必须要满足当前j,k的需求,所以我们在一开始还需要去维护一下加入前面1 - i - 1所有罐子都选的两个数值sum_n, sum_m只有当sum_n >= j && sum_m >= k 的时候我们才可以不去选择第I个罐子。 选择第i个罐子,此时f[i, j, k] = min(f[i, j, k], f[i - 1, j - a, k - b]);同时这里也需要加限制条件,加入当前sum_n + a < j && sum_m + b < k,那么表示即使选择了第i个罐子也不能满足需求,此时我们应该跳出内层的2层循环,让i ++;还有一种情况当sum_n + a >= j && sum_m + b <

动态规划-01背包-Tallest Billboard

白昼怎懂夜的黑 提交于 2020-02-07 19:20:09
2020-02-07 17:46:32 问题描述: 问题求解: 解法一:BF 看问题规模看似可以直接暴力解决。 如果直接去解肯定是会超时的,因为每次将原空间划分成A区域,B区域和剩余区域的时间复杂度为O(3 ^ n)。 但是我们可以将问题进行一下转化,之前有个问题是能否将一个数组中的数划分成两个和相等的子区域那个题目是可以使用dp完成求解的,时间复杂度是O(nsum)。 因此我们可以去构造出所有的挑选可能,并对每个可能产生解的可能去过一遍dp就能完成本题。 但是,本解法并不是最优解。 int ret = 0; int[] nums; List<Integer> res = new ArrayList<>(); public int tallestBillboard(int[] rods) { nums = rods; helper(0, 0); return ret; } private void helper(int start, int sum) { if (start >= nums.length) return; if (sum % 2 == 0 && check(res, sum / 2)) { ret = sum / 2; } helper(start + 1, sum); res.add(nums[start]); sum += nums[start]; if

问题 D: 小李打怪兽(01背包)

帅比萌擦擦* 提交于 2020-01-30 04:31:33
时间限制: 1 Sec 内存限制: 128 MB 提交: 115 解决: 54 [ 提交 ] [ 状态 ] [ 讨论版 ] [命题人:外部导入] 题目描述 小李对故乡的思念全部化作了对雾霾天气的怨念,这引起了掌控雾霾的邪神的极大不满,邪神派去了一只小怪兽去对付小李,由于这只怪兽拥有极高的IQ,它觉得直接消灭小李太没有难度了,它决定要和小李在智力水平上一较高下。我们可否帮助小李来战胜强大的怪兽呢? 问题是这样的:给定一堆正整数,要求你分成两堆,两堆数的和分别为 S1 和 S2 ,谁分的方案使得 S1*S1-S2*S2的结果小(规定S1>=S2),谁就将获得胜利。 注: S2 可以等于 0 。 输入 第一行 n ,表示共有 n 个数 第二行共 n 个用空格隔开的正整数 ai ,表示给定的一堆正整数。 输出 输出就一个整数,表示 S1*S1-S2*S2 的最小值。 样例输入 1 2 3 4 样例输出 0 提示 1 和 4 一堆, 2 和 3 一堆, 5*5-5*5 = 0 60% 的数据, 1<=n<=20 80% 的数据, 1<=n<=50 , ai<=20 100% 的数据, 1<=n<=100 , ai<=100 说实话我第一眼是排序贪心..然后分成两堆求,然后我自己举出了反例..这道题实际用01背包的知识点..我应该是最近在做线段树的模板题改模板和那种容易看出知识点的题做多了

POJ 2184 Cow Exhibition (01背包的变形)

蓝咒 提交于 2020-01-25 08:27:54
本文转载,出处: http://www.cnblogs.com/Findxiaoxun/articles/3398075.html 很巧妙的01背包升级。看完题目以后很明显有背包的感觉,然后就往背包上靠。把s看成是空间,f看成是价值,转换成了01背包经典模型(没有想到,,,)。可,s是负值,这就涉及到一个问题,如果按照普通的01背包,(01背包的倒序原因请参看这个 http://hi.baidu.com/findxiaoxun/item/9abf560127a155c091571868 ) for(int i=0;i<n;i++) for(int v=maxv;v>=vi[i];v--) dp[v]=max{dp[v],dp[v-vi[i]]+w[i]} 循环物品的时候,看第一件,在此题中,我们先假设最大空间为5,则2->5的值都为3, 然后i=1,循环第二件,v=5->3,而dp[5]=max{dp[5],dp[5+1]+4},背包空间为6的位置,我们假设预置为0,则dp[5]=4;dp[4]=max{dp[4],dp[4-(-1)]+4};则dp[4]=4+4=8;其实到这个值,我们已经看出,如果按照正常的逆序,s为负值的物品不只使用一次,这与题目的要求是相悖的。那么,正序考虑。读者可以自行推导,证明其可行性。 而我们发现,背包空间出现了负值,下限是-100*1000

完全背包

淺唱寂寞╮ 提交于 2020-01-13 18:52:09
什么是完全背包 完全背包,就是在背包容量有限的情况下,每件物品可以选无数多件。 如何求解完全背包 完全背包和01背包一样,拥有最优子结构。所以也可以用动态规划来解。 还是先确定动态转移方程,把01背包的转移方程进行发展,可以得到 f(n,m)=max{f(n-1,m-k×w[n] )+k×v[n] │ 0≤k×w[n]≤M} K表示选k件n类物品。其实01背包也可以用这个递推式来解的,只是k非0即1。 优化动态转移矩阵 如何优化这个转移矩阵呢?我们先回顾一下01背包是怎么优化的?我们把二维矩阵优化成一维数组,但是在计算时m要逆序。为怎么呢?因为第n件物品是不能复选的。 那我们在来看看如果m不逆序会发生什么? 我先们来看看“上次计算的结果”是什么呢?“上次计算的结果”无非是两种情况 f[n-2][m] 或者是 f[n-2][m-w[n-1] ]+v[n-1] 先考虑 第二种情况叠加 的情况,就会发现。。。我们根本没法叠加。但是如果我们把转移式改成 f[n][m]=max{f[n-1][m],f[n][m-w[n]]+v[n]} 就可以叠加了(就是后面那个n不减了)。结果发现这和 f(n,m)=max⁡{f(n-1,m-2×w[n] )+2×v[n]} 是等价的。那不就正好达到了取2件i物品的目的吗。在这样叠加上去,就和取k件i物品就等价了。这时候你可能会产生这样一个问题

c++ 动态规划-01背包

∥☆過路亽.° 提交于 2020-01-10 03:28:57
动态规划 - 01背包问题 1.使用递归遍历(穷举)求解: 01背包问题:给定 n 种物品和一个重量(容量)(限定条件)为 w 的 背包 ,物品 i 的重量是 wi,其价值为 vi。(每种物品只有一个)问:如何选择装入 背包 的物品,使得装入 背包 中的物品的价值最大。 //VC6.0-------------------------- #include"stdafx.h" #include <cmath> #include <iostream> using namespace std; //----------全局变量------------ #define n 4 //number //物品数量 #define max_w 9 //weight //可承受重量(最大重量) int value[n]={2,3,4,5}; //物品价值 int weight[n]={3,4,5,6}; //物品重量 //最大价值 以及解向量 int max_v=0; int x[n]={0}; int nx[n]={0}; //当前解的情况 //-----------------------递归----------------------- void beibao01(int i,int v,int w) //第i个物品 总价值 总重量 { //物品已遍历完毕 if(i>n-1) return;

背包问题详解

前提是你 提交于 2019-12-19 18:45:33
Nyoj289 苹果(01背包) 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 ctest有n个苹果,要将它放入容量为v的背包。给出第i个苹果的大小和价钱,求出能放入背包的苹果的总价钱最大值。 输入 有多组测试数据,每组测试数据第一行为2个正整数,分别代表苹果的个数n和背包的容量v,n、v同时为0时结束测试,此时不输出。接下来的n行,每行2个正整数,用空格隔开,分别代表苹果的大小c和价钱w。所有输入数字的范围大于等于0,小于等于1000。 输出 对每组测试数据输出一个整数,代表能放入背包的苹果的总价值。 样例输入 3 3 1 1 2 1 3 1 0 0 样例输出 2 #include<stdio.h> #include<string.h> #define N 1001 int dp[N]; int max(int a,int b) { if(a>b) return a; else return b; } int main() { int n,v,i,j,c,w; while(scanf("%d %d",&n,&v)) { if(n==0&&v==0) break; memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++) { scanf("%d %d",&c,&w); for(j=v;j>=c;j--) dp[j]=max

DP入门系列-背包问题-01背包

核能气质少年 提交于 2019-12-19 01:23:23
背包问题-01背包 背包问题一直以来都是用来学习DP的小白鼠,对于背包问题我曾经在DFS中有举过栗子,那么这一次我们用状态转移的思想来学习一下01背包。 什么是01背包呢?说白了就是这个物品拿与不拿的问题。也就是说我面临决策的时候都有两个方案,拿与不拿。但是拿与不拿均对后面的结果会产生影响,所以说你无法一眼就看出来最优解(optimal solution,下面我将用OPT来概述)。那么我们只能够把所有的情况枚举出来然后进行选择,选择的过程中我们会有很多的问题,当然对于DP的问题就是重复计算,于是我们考虑如何才能够用状态转移把这个问题解决了。 首先推荐一个博客网站 DP初学者必备,WOC太牛逼了!!!QAQ 那么我们先来搬运一道题目来揭开我们今天的帷幕。 题目描述 有 N件物品和一个容量是 V 的背包。每件物品只能使用一次。第 i 件物品的体积是 vi,价值是 wi。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。 输入格式 第一行两个整数N,V,用空格隔开,分别表示物品数量和背包容积。下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。 输出格式 输出一个整数,表示最大价值。 数据范围 0<N,V≤1000 0<vi,wi≤1000 Sample Input 4 5 1 2 2 4 3 4 4 5