贪心算法最优装载
‘壹’ 贪心算法的本质
1. 贪心法(Greedy Algorithm)定义
求解最优化问题的算法通常需要经过一系列的步骤,在每个步骤都面临多种选择;
贪心法就是这样的算法:它在每个决策点作出在当时看来最佳的选择,即总是遵循某种规则,做出局部最优的选择,以推导出全局最优解(局部最优解->全局最优解)
2. 对贪心法的深入理解
(1)原理:一种启发式策略,在每个决策点作出在当时看来最佳的选择
(2)求解最优化问题的两个关键要素:贪心选择性质+最优子结构
①贪心选择性质:进行选择时,直接做出在当前问题中看来最优的选择,而不必考虑子问题的解;
②最优子结构:如果一个问题的最优解包含其子问题的最优解,则称此问题具有最优子结构性质
(3)解题关键:贪心策略的选择
贪心算法不是对所有问题都能得到整体最优解的,因此选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
(4)一般步骤:
①建立数学模型来描述最优化问题;
②把求解的最优化问题转化为这样的形式:对其做出一次选择后,只剩下一个子问题需要求解;
③证明做出贪心选择后:
1°原问题总是存在全局最优解,即贪心选择始终安全;
2°剩余子问题的局部最优解与贪心选择组合,即可得到原问题的全局最优解。
并完成2°
3. 贪心法与动态规划
最优解问题大部分都可以拆分成一个个的子问题,把解空间的遍历视作对子问题树的遍历,则以某种形式对树整个的遍历一遍就可以求出最优解,大部分情况下这是不可行的。贪心算法和动态规划本质上是对子问题树的一种修剪,两种算法要求问题都具有的一个性质就是子问题最优性(组成最优解的每一个子问题的解,对于这个子问题本身肯定也是最优的)。动态规划方法代表了这一类问题的一般解法,我们自底向上构造子问题的解,对每一个子树的根,求出下面每一个叶子的值,并且以其中的最优值作为自身的值,其它的值舍弃。而贪心算法是动态规划方法的一个特例,可以证明每一个子树的根的值不取决于下面叶子的值,而只取决于当前问题的状况。换句话说,不需要知道一个节点所有子树的情况,就可以求出这个节点的值。由于贪心算法的这个特性,它对解空间树的遍历不需要自底向上,而只需要自根开始,选择最优的路,一直走到底就可以了。
‘贰’ 如何证明最优装载问题具有贪心选择性质
设某种货币系统为(1,5,10,25)四种币值(单位:元),要用最少的币数找出 n元钱,
问:能否用贪心算法进行求解,并证明。(不要求写算法) 参考解答:贪心性质(最大面额优先选最多)证明:
对 n<=25的情况,易由穷举得证。
当 n>25时,设 n=1*a1+5*a2+10*a3+25*a4
为了使 a1+a2+a3+a4最小,易知:
a1<5,若 a1>=5,可将 5个 1元兑换为 1个 5元,币数减少。
a2<2,若 a2>=2,可将 2个 5元兑换为 1个 10元,币数减少。
当 a2=0时,a3<3,若 a3>=3,可将 3个 10元兑换为 1个 5元和 1个 25元,币数减 少。
当 a2>0时,a3<2,若 a2>=2,可将 1个 5元和 2个 10元兑换为 1个 25元,币数减 少。
即,为了使 a1+a2+a3+a4最小,所使用的 1、5、10元币的币数的上限为: a1=4,a2=0,a3=2或 a1=4,a2=1,a3=1
则所使用的 1、5、10元币的币值上限为:
4*1+0*5+2*10=24或 4*1+1*5+1*10=19
均不超过 25,因此,为了使 a1+a2+a3+a4最小,应使 a4达到最大。贪心选择性质得 证。
最优子结构性质证明:
当 a4的值确定后,为了使 a1+a2+a3+a4达到最小,须使 a1+a2+a3达到最小,仍为同 型的最优问题。
‘叁’ 贪心算法的最优装载问题
void loading(W[],X[],c,n)
{
for(i=1,i<n,i++)
1.void loading(int W[],int X[],int c,int n)
2.没有定义i;
3.for(;;)是冒号,非逗号
‘肆’ 怎样应用贪心算法求得最优解
动态规划要求。。具有最优子结构,记f[i]最优时,f[i - 1]的解也最优。。。最终可以得到最优解
贪心算法,一般只能得到近优解或者局部最优解。。
‘伍’ 什么是贪心算法
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。
‘陆’ 最优装载:有一批集装箱要装上一艘载重量为totalW的轮船,其中集装箱i的重量为wi。最有装载问题要求在装在
453453
‘柒’ 漫谈算法如何证明贪心算法是最优 using exchange argument
这里主要是介绍一种证明贪心算法是最优的一种方法:Exchange Argument (不知道应该怎么翻译到中文,交换参数?感觉听起来挺别扭的,不像是一个方法的名字~o( □ )o)
Exchange Argument的主要的思想也就是 先假设 存在一个最优的算法和我们的贪心算法最接近,然后通过交换两个算法里的一个步骤(或元素),得到一个新的最优的算法,同时这个算法比前一个最优算法更接近于我们的贪心算法,从而得到矛盾,原命题成立。
下面来看一个更为formal的解释:
步骤:
Step0: 给出贪心算法A的描述
Step1: 假设O是和A最相似(假设O和A的前k个步骤都相同,第k+1个开始不同,通常这个临界的元素最重要)的最优算法
Step2: [Key] 修改算法O(用Exchange Argument,交换A和O中的一个元素),得到新的算法O’
Step3: 证明O’ 是feasible的,也就是O’是对的
Step4: 证明O’至少和O一样,即O’也是最优的
Step5: 得到矛盾,因为O’ 比O 更和A 相似。
证毕。
当然上面的步骤还有一个变种,如下:
Step0: 给出贪心算法A的描述
Step1: 假设O是一个最优算法(随便选,arbitrary)
Step2: 找出O和A中的一个不同。(当然这里面的不同可以是一个元素在O不再A,或者是一个pair的顺序在A的和在O的不一样。这个要根据具体题目)
Step3:Exchange这个不同的东西,然后argue现在得到的算法O 不必O差。
Step4: Argue 这样的不同一共有Polynomial个,然后我exchange Polynomial次就可以消除所有的不同,同时保证了算法的质量不比O差。这也就是说A 是as good as 一个O的。因为O是arbitrary选的,所以A是optimal的。
证毕
下面给几个例子:
例 Maximum Cardinality Disjoint Interval Problem
问题描述:给一些时间片段集合T={(a1,b1)(a2,b2),。。。,(an,bn)},找出一个元素个数最多的子集S,子集中的每个元素的时间片段没有交叉。
Greedy Algorithm: 每次都选所有interval 中bi最小的那个,把(ai,bi)加入S,然后把(ai,bi)在T中删除,同时把T中所有和(ai,bi)有交叉的interval删除,然后再在T中找最小的bj,循环上面的操作,直到没有可以在添加的。
证明上面说的Greedy Algorithm是最优的。
下面就用第一个证明的步骤来证。
我们的Greedy Algorithm记为A,假设A不是最优的,那么就一定存在一个O,O是和A最相近的一个最优的算法,最相近是指和O和A的前K-1个选择都相同,第K个是不同的。
假设对于A,A第k个选择的是(ai,bi);而O第K个选择的是(aj,bj)。从A的定义我们可以直到,bi<=bj。
‘捌’ 如何用贪心算法解决磁盘文件最优存储问题
dp??
方程为
a(fi,fj)=min{(a(fi,fk)+a(fk,fj)),a(fi,fj)}(k=i+1,i+2...j-1);
‘玖’ 为什么贪心算法可用于解决最优化问题
最优化问题是程序设计中一类非常重要的问题。每一个最优化问题都包含一组约束条件和一个优化函数,满足约束条件的问题求解方案称为问题的可行解,使优化函数取得最优值的可行解称为问题的最优解。贪婪算法是解决最优化问题的一种基本方法。
它采用逐步构造最优解的思想,在问题求解的每一个阶段,都作出一个在一定标准下看上去最优的决策;决策一旦作出,就不可再更改。制定决策的依据称为贪婪准则。