贪心算法

算法设计与分析-贪心算法

时光总嘲笑我的痴心妄想 提交于 2020-03-13 19:53:36
所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。 贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。 贪心算法的基本思路如下: 1.建立数学模型来描述问题。 2.把求解的问题分成若干个子问题。 3.对每一子问题求解,得到子问题的局部最优解。 4.把子问题的解局部最优解合成原来解问题的一个解。 实现该算法的过程: 从问题的某一初始解出发; while 能朝给定总目标前进一步 do 求出可行解的一个解元素; 由所有解元素组合成问题的一个可行解; 下面是一个可以试用贪心算法解的题目,贪心解的确不错,可惜不是最优解。 例题分析 [背包问题]有一个背包,背包容量是M=150。有7个物品,物品可以分割成任意大小。 要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。 物品 A B C D E F G 重量 35 30 60 50 40 10 25 价值 10 40 30 50 35 40 30 分析: 目标函数: ∑pi最大 约束条件是装入的物品总重量不超过背包容量:∑wi<=M( M=150) (1)根据贪心的策略,每次挑选价值最大的物品装入背包,得到的结果是否最优? (2)每次挑选所占重量最小的物品装入是否能得到最优解? (3

C++ 贪心算法最优装载问题

喜夏-厌秋 提交于 2020-03-09 03:15:26
最优装载: 有一批集装箱要装上一艘载重量为c的轮船,其中集装箱i的重量为wi。最优装载问题要求确定在装载体积不受限制的情况下,将尽可能多的集装箱装上轮船。 贪心策略:先轻后重 # include <iostream> # include <algorithm> using namespace std ; struct load { //结构体定义集装箱的编号和重量 int index ; int w ; } box [ 1001 ] ; //初始化结构体数组 bool cmp ( load a , load b ) { //自定义sort函数cmp,按照从小到大的顺序排列 if ( a . w < b . w ) return true ; else return false ; } ; int main ( ) { int c , n ; //c为货船的载重,n为集装箱的个数 int x [ 1001 ] ; //此数组用来控制已装载的集装箱编号 while ( cin >> c >> n ) { memset ( box , 0 , sizeof ( box ) ) ; //每次输入都要将数组box和x清零 memset ( x , 0 , sizeof ( x ) ) ; for ( int i = 1 ; i <= n ; i ++ ) { cin >> box [ i ]

递归,贪心

我的未来我决定 提交于 2020-03-09 00:25:47
递归 递归算法是指程序直接或间接调用自身的技巧;他通常把一个大型复杂问题层层转化为一个与原问题相似的规模较小的问题来求解。其基本思想为层层分解,关键在于找出递归定义和终止条件。 例题 G:括号匹配问题 字符串(长度不超过100)中有左括号、右括号和大小写字母;规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配。写一个程序,找到无法匹配的左括号和右括号,输出原来字符串,并在下一行标出不能匹配的括号。不能匹配的左括号用"$“标注,不能匹配的右括号用”?"标注. Input 输入包括多组数据,每组数据一行,包含一个字符串,只包含左右括号和大小写字母,字符串长度不超过100 注意:cin.getline(str,100)最多只能输入99个字符! Output 对每组输出数据,输出两行,第一行包含原始输入字符,第二行由" " , " ? " 和 空 格 组 成 , " ","?"和空格组成," " , " ? " 和 空 格 组 成 , " “和”?"表示与之对应的左括号和右括号不能匹配。 SAMPLE INPUT ((ABCD(x) )(rttyy())sss)( SAMPLE OUTPUT ((ABCD(x) $$ )(rttyy())sss)( ? ?$ 为解决此问题引入STACK函数 # include <iostream> # include

贪心算法1

谁说胖子不能爱 提交于 2020-03-08 15:18:51
1、 学前须知 这是一种求 最优解 的方法。它是按照某种 最优策略 ,将复杂问题层层分解成子问题( 每次一般只有一个 ),并由子问题的最优解“回溯”出整个问题的最优解。贪心算法不是从整体上考虑问题,它所做出的选择只是在 某种意义上的局部最优解 ,而由问题自身的特性决定了该题运用贪心算法可以得到最优解。如果一个问题可以同时用几种方法解决,贪心算法应该是其中最好的解决方法 2、 在利用贪心策略解决问题时,我们应该提前解决两个问题 (1)第一个问题是 该题是否适合于用贪心策略求解; (2)第二个我们要解决的问题是 我们应该如何选择贪心标准,以得到问题的最优/较优解,即制定贪心策略。 3、 光说不练假把式,下面我们来用几道例题来学习贪心算法 1. 最优装载问题 ① 问题描述 :有一批集装箱要装上一艘载重量为c的轮船,其中集装箱i的重量为wi。最优装载问题要求确定在装载体积不受限制的情况下,将尽可能多的集装箱装上轮船。 ②贪心策略 :先将轻的箱子放在船上 ③代码实现 # include <iostream> # include <algorithm> //使用sort前需要加上algorithm的函数头 using namespace std ; struct load //用结构体将index与w绑在一起 { int index ; //集装箱的编号 int w ; //集装箱的重量 }

贪心算法

纵饮孤独 提交于 2020-03-07 08:33:14
VonGang原创,如有错误,欢迎指正。转载请注明: http://www.cnblogs.com/vongang/ 贪心算法的思想在于只求局部最优,不管全局如何。但是这样得出的结果往往也是全局最优的,当然也有的不是全局最优。 以背包问题为例:  [背包问题]有一个背包,背包容量是M=150。有7个物品,物品不可以分割成任意大小。 要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。   物品 A B C D E F G   重量 35 30 60 50 40 10 25   价值 10 40 30 50 35 40 30   分析:   目标函数: ∑pi最大   约束条件是装入的物品总重量不超过背包容量:∑wi<=M( M=150)   (1)根据贪心的 策略 ,每次挑选价值最大的物品装入背包,得到的结果是否最优?   (2)每次挑选所占重量最小的物品装入是否能得到最优解?   (3)每次选取单位重量价值最大的物品,成为解本题的策略。   值得注意的是,贪心算法并不是完全不可以使用,贪心策略一旦经过证明成立后,它就是一种高效的算法。   贪心算法还是很常见的算法之一,这是由于它简单易行,构造贪心策略不是很困难。   可惜的是,它需要证明后才能真正运用到题目的算法中。   一般来说,贪心算法的证明围绕着:整个问题的最优解一定由在贪心策略中存在的子问题的最优解得来的。  

贪心算法

陌路散爱 提交于 2020-03-03 15:48:02
目录 思想 条件 贪心算法正确性的证明() 贪心选择的证明,方法一: 贪心选择的证明,方法二——剪枝法: 最优子结构证明: 应用:活动选择问题 贪心选择的证明 应用:Huffman编码 算法 证明贪心选择性质 证明最优子结构性质 用huffman编码斐波那契数 应用:最小生成树( Kruskal Algorithm for Minimum Spanning Tree) 贪心算法正确性证明 删数问题 其他应用 胚(matroids) 定义 最大独立子集 加权胚和最优子集 @ 贪心算法(Greedy Algorithms) 思想 每次选择总是选出当前最优的解 特点 :只计算部分子问题,而动态规划需要计算全部子问题,但同样依赖最优子结构性质。 步骤 :先排个序,再按每次最优循环选择。 条件 最优子结构性质 问题的整体最优解中包含子问题的最优解 贪心选择性质:局部最优=>全局最优 本次贪心选择与剩余子问题的最优解可以构成原问题的最优解。 贪心算法正确性的证明() 包括两部分:贪心选择性质的证明和最优子结构证明 贪心选择的证明,方法一: 给出贪心算法A的描述 反证:先给出一个贪心算的最优解A,然后假设非贪心选择的B是最优解,B可由A序列中调换元素 得到,证明B的解值比A差。 贪心选择的证明,方法二——剪枝法: 贪心算法A的描述 假设O是一个最优算法 找出O和A中的一个不同

算法思想

你说的曾经没有我的故事 提交于 2020-03-03 09:34:52
1.算法思想的概念 ================================================================================================ 1.1贪心--贪心思想 ======================================================================================================= 1.1.1 贪心--背包问题 ========================================================================================================================= 1.1.2 贪心--贪心算法思考 ======================================================================================================== 1.2、贪心-贪心算法应用场景 ======================================================================================================

NOIP 双栈排序(贪心算法)

跟風遠走 提交于 2020-02-26 22:38:58
题目描述 Tom最近在研究一个有趣的排序问题。如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序。 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1不为空,将S1栈顶元素弹出至输出序列 操作c 如果输入序列不为空,将第一个元素压入栈S2 操作d 如果栈S2不为空,将S2栈顶元素弹出至输出序列 如果一个1~n的排列P可以通过一系列操作使得输出序列为1,2,…,(n-1),n,Tom就称P是一个“可双栈排序排列”。例如(1,3,2,4)就是一个“可双栈排序序列”,而(2,3,4,1)不是。下图描述了一个将(1,3,2,4)排序的操作序列:<a,c,c,b,a,d,d,b> 当然,这样的操作序列有可能有几个,对于上例(1,3,2,4),<a,c,c,b,a,d,d,b>是另外一个可行的操作序列。Tom希望知道其中字典序最小的操作序列是什么。 【输入】 输入文件twostack.in的第一行是一个整数n。 第二行有n个用空格隔开的正整数,构成一个1~n的排列。 【输出】 输出文件twostack.out共一行,如果输入的排列不是“可双栈排序排列”,输出数字0;否则输出字典序最小的操作序列,每两个操作之间用空格隔开,行尾没有空格。 【输入输出样例1】 输入: 4 1 3 2 4 输出: a b a a b b a b 思路 能弹出,则弹出

贪心算法

醉酒当歌 提交于 2020-02-26 13:13:45
贪心算法是指对于解决问题的每一步都作出最优解,从而希望得到最后的结果也是最优解,但是最后结果不一定都是最优解,大部分都是最接近最优解的结果 具体在百度百科的基本思路里有很好的解释,这里就不详写了 用贪心算法解决覆盖问题: import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; public class GreedyAlgorithm { public static void main(String[] args) { HashMap<String, HashSet<String>> broadcasts = new HashMap<>(); HashSet<String> hashSet = new HashSet<>(); hashSet.add("北京"); hashSet.add("上海"); hashSet.add("天津"); HashSet<String> hashSet2 = new HashSet<>(); hashSet2.add("广州"); hashSet2.add("北京"); hashSet2.add("深圳"); HashSet<String> hashSet3 = new HashSet<>(); hashSet3.add("成都");

算法常见概念

僤鯓⒐⒋嵵緔 提交于 2020-02-25 08:02:22
一个算法应该具有以下五个重要的特征: 1、有穷性: 一个算法必须保证执行有限步之后结束; 2、确切性: 算法的每一步骤必须有确切的定义; 3、输入:一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0个输入是指算法本身定除了初始条件; 4、输出:一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出的算法是毫无意义的; 5、可行性: 算法原则上能够精确地运行,而且人们用笔和纸做有限次运算后即可完成。 常见的算法 1.分治法 字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法( 快速排序 、 归并排序 )、 傅立叶变换 ( 快速傅立叶变换 )。另一方面,理解及设计分治法算法的能力需要一定时间去掌握。正如以归纳法去证明一个 理论 ,为了使递归能够推行,很多时候需要用一个较为概括或复杂的问题去取代原有问题。而且并没有一个系统性的方法去适当地概括问题。 2.动态规划法 动态规划在查找有很多 重叠子问题 的情况的最优解时有效。它将问题重新组合成子问题。为了避免多次解决这些子问题,它们的结果都逐渐被计算并被保存,从简单的问题直到整个问题都被解决。因此,动态规划保存递归时的结果,因而不会在解决同样的问题时花费时间。 动态规划只能应用于有