背包问题

贪心策略

回眸只為那壹抹淺笑 提交于 2019-12-19 12:38:58
之所以称之为“策略”,而不是“算法”,还是有些原因的,贪心思想和动态规划思想练习紧密,可是细想一下有不能混为一谈,动态规划是根据迁移过程的状态去推导下一过程的状态,是有理论依据的,通过每次“完美”的检验而得出最优解,关键是找出一个最优子结构,记得经典的一句话是:动态规划的子结构必须是独立的,而且是重叠的,虽然是一组反义词,可是代表的意义是不同的。扯远了,而贪心策略不同,贪心只考虑当前的最优解,是临时的,不连续的,所以得出的解不一定是最优解。 一个最间的的例子就是0-1背包问题,根据贪心,每次都放进去最“实惠”的,也就是“性价比”最高的,然后放次高的,直到不能放,这样做显然是不尽人意的,因为贪心策略没有考虑到背包的容量,为什么?前面说过了,贪心策略只考虑当前的最优解,他是不会管背包容量的,如果加入了背包容量这个参数,便成为DP问题了,贪心策略缺少一约束条件,贪心找出的每一条路径都是最大可能接近最优解的,例如:每条路径是最优解的可能性是0.8,贪心一共做了4次检查,于是正确的最优解得可能是(0.8)^4,可是他没有考虑其他的情况,问题就出现了。当然,贪心也有很多正确的策略,只是不适用某一问题罢了。 *********************************************************************** 下面开始看看贪心算法: 一.贪心算法的基本概念

可用贪心算法解决的几个基本问题

我的梦境 提交于 2019-12-19 12:38:40
可用贪心算法解决的几个基本问题 分类: 算法 2011-08-24 12:36 950人阅读 评论 (0) 收藏 举报 算法 活动 作业 c 关键:看问题有没有贪心选择性质和最优子结构性质。有些问题看似是可以用贪心算法,但是实际用贪心算法却得不到最优解。构造贪心算法后,需要一定的证明来确定它的正确性。常用证明方法:反证法、调整法。 几个基本问题: 1. 活动安排问题。 设有n个活动的集合e={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和一个结束时间f i ,且s i <f i 。如果选择了活动i,则它在区间[s i ,f i ]内占用资源。若区间[s i ,f i ]与区间[s j ,f j ]不相交,则称活动i与活动j是相容的。也就是说,当s j ≥fi或s i ≥f j 时,活动i与活动j相容。活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合。 解决方法:先选择结束时间最早的那一个活动,然后往后依次查找结束时间最近的不冲突的活动加入。 2. 可以解决背包问题,不能解决0-1背包问题。 0-1背包问题: 给定n种物品和一个背包。物品i的重量是Wi,其价值为Vi,背包的容量为C。应如何选择装入背包的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时

【多重背包】HDU-1059 Dividing

你离开我真会死。 提交于 2019-12-19 05:45:03
注解 1、背包问题主要分为三种:01背包、完全背包和多重背包。 其中01背包是指每种物品只有一个,要么选,要么不选。 完全背包是指物品数目有无限个,可以选择任意多个,只要满足总容量小于等于背包容量就可以。 多重背包是指物品数目有有限个,但不止一个,可以选择多个。 2、本题的多重背包可以化为完全背包和01背包的结合。其中,每种物品的数目,可以选择将数目二进制化,然后化为多个物品,如13个,可以化为0001,0010,0100,0110这四个不同的物品(分别是1个,2个,4个,6个该物品),因此选择的数目就可以任意组合(从1-13的数目均可以组合出来),且将问题转化为了01背包问题。 代码 # include <iostream> # include <cstring> using namespace std ; const int MAX = 6 ; const int MAXV = 60010 ; int d [ MAXV ] , V ; void bag01 ( int c , int w ) { for ( int i = V ; i >= c ; i -- ) { d [ i ] = max ( d [ i ] , d [ i - c ] + w ) ; } } void bagall ( int c , int w ) { for ( int i = c ; i <= V

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

回溯法解决0-1背包问题

て烟熏妆下的殇ゞ 提交于 2019-12-17 00:18:47
问题描述:    有 n 件物品和一个容量为 c 的背包。第 i件物品的价值是 v [i],重量是 w[i]。求解将哪些物品装入背包可使价值总和最大。 所谓01背包,表示每一个物品只有一个,要么装入,要么不装入。 回溯法 :   01背包属于找最优解问题,用回溯法需要构造解的子集树。在搜索状态空间树时,只要左子节点是可一个可行结点,搜索就进入其左子树。对于右子树时,先计算上界函数,以判断是否将其减去,剪枝啦啦! 上界函数bound():当前价值cw+剩余容量可容纳的最大价值<=当前最优价值bestp。 为了更好地计算和运用上界函数剪枝,选择先将物品按照其单位重量价值从大到小排序,此后就按照顺序考虑各个物品。 #include <stdio.h> #include <conio.h> int n;//物品数量 double c;//背包容量 double v[100];//各个物品的价值 double w[100];//各个物品的重量 double cw = 0.0;//当前背包重量 double cp = 0.0;//当前背包中物品价值 double bestp = 0.0;//当前最优价值 double perp[100];//单位物品价值排序后 int order[100];//物品编号 int put[100];//设置是否装入 //按单位价值排序 void knapsack

动态规划0-1背包问题

你。 提交于 2019-12-16 21:29:10
最近看了一些简单的动态规划方面的例题 在学习的过程中发现 有的问题虽然不难 但是第一次看还是会有些问题 所以把自己弄0-1背包的问题拿出来给大家分享 不喜勿喷 网上资源特别多 讲解什么的就算了 其他人画的图都不错 递推关系 : 设所给 0-1 背包问题 的最优值为 m(i , j) ,即 m(i , j) 是背包容量为 j ,可选择物品为 i , i+1 , … , n 时 0-1 背包问题的最优值。由 0-1 背包问题的最优子结构性质,可以建立计算 m(i , j) 的递归式 : 上 式此时背包容量为 j ,可选择物品为 i 。此时在对 xi 作出决策之后 , 问题处于两种状态之一 : (1) 背包剩余容量是 j, 没产生任何效益; (2) 剩余容量 j-wi, 效益值增长了 vi ; 我写的代码 看完看有没有启发 package org.bq.dp; /** * 0-1背包问题 * * @author 白强原创 * @version 1.0 */ public class OneZero { // 最大背包容量 private static final int M = 10; // 物品数量 private static final int N = 3; // 物品重量数组 给它数组前面加一个0项是为了更好的表达这种关系 比方从一个到全部物品的时候i=2的使用w[i]

dp--01背包--Bone Collector

南楼画角 提交于 2019-12-16 10:56:06
Bone Collector 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

动态规划之背包问题

让人想犯罪 __ 提交于 2019-12-15 13:13:53
背包问题是动态规划的一个分支,这里先简单介绍一下动态规划的思想。 动态规划程序设计是对解最优化问题的一种途径、一种方法,而不是一种特殊算法。不像搜索或数值计算那样,具有一个标准的数学表达式和明确清晰的解题方法。动态规划程序设计往往是针对一种最优化问题,由于各种问题的性质不同,确定最优解的条件也互不相同,因而动态规划的设计方法对不同的问题,有各具特色的解题方法,而不存在一种万能的动态规划算法,可以解决各类最优化问题。因此在学习时,除了要对基本概念和方法正确理解外,必需具体问题具体分析处理,以丰富的想象力去建立模型,用创造性的技巧去求解。我们也可以通过对若干有代表性的问题的动态规划算法进行分析、讨论,逐渐学会并掌握这一设计方法。(以上来自百度百科) 简单来说动态规划是一个思想,而不是一个固定的算法模板,我们需要通过这种思想确定状态转移方程(一个好的状态),然后再求解。 动态规划适用于很多情况,其中一些情况被统一划分归类,而背包问题则是一种最为常见的动态规划问题。 背包问题又分为许多种,如:01背包,完全背包等 我们这里介绍最为常见的三种,分别是01背包,完全背包,和多重背包。 1.01背包 这是一个经典的动态规划问题,另外在贪心算法里也有背包问题,至于二者的区别在此就不做介绍了。 题目一般都是有 N件物品和一个容量为 V的背包。第 i件物品的体积是 v[i],价值是 c[i]

PTA

丶灬走出姿态 提交于 2019-12-14 21:37:09
回溯法0-1背包 (50分) 给定n(n<=100)种物品和一个背包。物品i的重量是wi,价值为vi,背包的容量为C(C<=1000)。问:应如何选择装入背包中的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时,对每种物品i只有两个选择:装入或不装入。不能将物品i装入多次,也不能只装入部分物品i。 输入格式: 共有n+1行输入: 第一行为n值和c值,表示n件物品和背包容量c; 接下来的n行,每行有两个数据,分别表示第i(1≤i≤n)件物品的重量和价值。 输出格式: 输出装入背包中物品的最大总价值。 输入样例: 在这里给出一组输入。例如: 5 10 2 6 2 3 6 5 5 4 4 6 输出样例: 在这里给出相应的输出。例如: 15 //回溯法背包问题 //先把第一个初始化重量小于它则q更新为1(A)然后价格q.a【i】也进行更新i是从1到n即把能装进去的都装一遍 //循环第二个q=2(B),若能装进去第二个则判断装进去第二个后和剩下空间装进去的和与原来对应A位置处的价值相比大则装,不大则不装 //要是不能装进去则价值为原来A位置对应价值 # include <iostream> using namespace std ; const int N = 101 ; const int C = 1001 ; struct thing { int weight ; //质量

问题 Y: 01背包问题(第五讲)

纵饮孤独 提交于 2019-12-11 07:24:42
题目描述 有容积为w的背包,有n个物品,并且已知每个物品的体积和价值,找到一种方法将若干物品放入背包,使背包中物品的总价值最大。输入物品件数n、背包容积w、每个物品的体积和价值,输出可以装入背包中的物品的最大总价值。n不大于15。 输入 在第一行输入物品件数n和背包容积w,在下一行输入n个整数表示n个物品的体积,在第三行输入n个整数表示n个物品的价值。遇到文件末尾结束。 输出 在一行输出可以得到的背包中物品的最大总价值。 样例输入 4 8 2 4 4 3 3 4 3 6 样例输出 10 #include <bits/stdc++.h> using namespace std; int ww[16],vv[16],s[16]; int n,w,v,maxv; void knapsack(int n){ if(w==0||n==0){ if(v>maxv) maxv=v; return ; } if(w>=ww[n]){//如果可以,尝试装下物品n后在装下n-1个物品 v+=vv[n]; w-=ww[n]; s[n]=1; knapsack(n-1); v-=vv[n];//回溯,状态回复 w+=ww[n]; s[n]=0; } knapsack(n-1); } int main(){ int i; while(~scanf("%d%d",&n,&w)){ for(i=1;i<=n;i