贪心算法习题解析
贪心算法-01背包问题
![贪心算法-01背包问题](https://img.taocdn.com/s3/m/18ae521ff08583d049649b6648d7c1c708a10bf6.png)
贪⼼算法-01背包问题1、问题描述:给定n种物品和⼀背包。
物品i的重量是wi,其价值为vi,背包的容量为C。
问:应如何选择装⼊背包的物品,使得装⼊背包中物品的总价值最⼤?形式化描述:给定c >0, wi >0, vi >0 , 1≤i≤n.要求找⼀n元向量(x1,x2,…,xn,), xi∈{0,1}, ∋ ∑ wi xi≤c,且∑ vi xi达最⼤.即⼀个特殊的整数规划问题。
2、最优性原理:设(y1,y2,…,yn)是 (3.4.1)的⼀个最优解.则(y2,…,yn)是下⾯相应⼦问题的⼀个最优解:证明:使⽤反证法。
若不然,设(z2,z3,…,zn)是上述⼦问题的⼀个最优解,⽽(y2,y3,…,yn)不是它的最优解。
显然有∑vizi > ∑viyi (i=2,…,n)且 w1y1+ ∑wizi<= c因此 v1y1+ ∑vizi (i=2,…,n) > ∑ viyi, (i=1,…,n)说明(y1,z2, z3,…,zn)是(3.4.1)0-1背包问题的⼀个更优解,导出(y1,y2,…,yn)不是背包问题的最优解,⽭盾。
3、递推关系:设所给0-1背包问题的⼦问题的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。
由0-1背包问题的最优⼦结构性质,可以建⽴计算m(i,j)的递归式:注:(3.4.3)式此时背包容量为j,可选择物品为i。
此时在对xi作出决策之后,问题处于两种状态之⼀:(1)背包剩余容量是j,没产⽣任何效益;(2)剩余容量j-wi,效益值增长了vi ;使⽤递归C++代码如下:#include<iostream>using namespace std;const int N=3;const int W=50;int weights[N+1]={0,10,20,30};int values[N+1]={0,60,100,120};int V[N+1][W+1]={0};int knapsack(int i,int j){int value;if(V[i][j]<0){if(j<weights[i]){value=knapsack(i-1,j);}else{value=max(knapsack(i-1,j),values[i]+knapsack(i-1,j-weights[i]));}V[i][j]=value;}return V[i][j];}int main(){int i,j;for(i=1;i<=N;i++)for(j=1;j<=W;j++)V[i][j]=-1;cout<<knapsack(3,50)<<endl;cout<<endl;}不使⽤递归的C++代码:简单⼀点的修改//3d10-1 动态规划背包问题#include <iostream>using namespace std;const int N = 4;void Knapsack(int v[],int w[],int c,int n,int m[][10]);void Traceback(int m[][10],int w[],int c,int n,int x[]);int main(){int c=8;int v[]={0,2,1,4,3},w[]={0,1,4,2,3};//下标从1开始int x[N+1];int m[10][10];cout<<"待装物品重量分别为:"<<endl;for(int i=1; i<=N; i++){cout<<w[i]<<" ";}cout<<endl;cout<<"待装物品价值分别为:"<<endl;for(int i=1; i<=N; i++){cout<<v[i]<<" ";}cout<<endl;Knapsack(v,w,c,N,m);cout<<"背包能装的最⼤价值为:"<<m[1][c]<<endl;Traceback(m,w,c,N,x);cout<<"背包装下的物品编号为:"<<endl;for(int i=1; i<=N; i++){if(x[i]==1){cout<<i<<" ";}}cout<<endl;return 0;}void Knapsack(int v[],int w[],int c,int n,int m[][10]){int jMax = min(w[n]-1,c);//背包剩余容量上限范围[0~w[n]-1] for(int j=0; j<=jMax;j++){m[n][j]=0;}for(int j=w[n]; j<=c; j++)//限制范围[w[n]~c]{m[n][j] = v[n];}for(int i=n-1; i>1; i--){jMax = min(w[i]-1,c);for(int j=0; j<=jMax; j++)//背包不同剩余容量j<=jMax<c{m[i][j] = m[i+1][j];//没产⽣任何效益}for(int j=w[i]; j<=c; j++) //背包不同剩余容量j-wi >c{m[i][j] = max(m[i+1][j],m[i+1][j-w[i]]+v[i]);//效益值增长vi }}m[1][c] = m[2][c];if(c>=w[1]){m[1][c] = max(m[1][c],m[2][c-w[1]]+v[1]);}}//x[]数组存储对应物品0-1向量,0不装⼊背包,1表⽰装⼊背包void Traceback(int m[][10],int w[],int c,int n,int x[]){for(int i=1; i<n; i++){if(m[i][c] == m[i+1][c]){x[i]=0;}else{x[i]=1;c-=w[i];}}x[n]=(m[n][c])?1:0;}运⾏结果:算法执⾏过程对m[][]填表及Traceback回溯过程如图所⽰:从m(i,j)的递归式容易看出,算法Knapsack需要O(nc)计算时间; Traceback需O(n)计算时间;算法总体需要O(nc)计算时间。
背包问题解析(一)-贪心算法
![背包问题解析(一)-贪心算法](https://img.taocdn.com/s3/m/19e35e1217fc700abb68a98271fe910ef12daebb.png)
背包问题解析(⼀)-贪⼼算法⼀、题⽬:有N件物品和⼀个容量为V的背包。
第i件物品的重量是w[i],价值是v[i]。
求解将哪些物品装⼊背包可使这些物品的重量总和不超过背包容量,且价值总和最⼤。
⼆、解决思路:本题刚开始的解题的时候,想采取贪⼼算法来解决,也就是将放⼊的物品的性价⽐按照从⾼到低进⾏排序,然后优先放优先级⾼的,其次优先级低的。
三、代码实现(python)1# 重量w=[5,4,3,2]2# 价值v=[6,5,4,3]3 b=[]4 m=int(input("请输⼊背包的最⼤重量:"))5 n=int(input("请输⼊商品的数量:"))6for i in range(n):7 a=input("请分别输⼊重量和价值,以空格隔开:")8 a=a.split("")9for i in range(len(a)):10 a[i]=int(a[i])11 b.append(a)12print("加载初始化:",b)13for i in range(len(b)):14for j in range(i+1,len(b)):15if b[i][1]/b[i][0]<b[j][1]/b[j][0]:16 b[i],b[j]=b[j],b[i]17print("性价⽐排序:",b)18 v=019 c=[]20for i in range(len(b)):21if m-b[i][0]>0:22 m=m-b[i][0]23 c.append(b[i])24 v+=b[i][1]25print("放⼊背包:",c)26print("最⼤价值为:",v)打印结果:四、算法分析:贪⼼选择是指所求问题的整体最优解可以通过⼀系列局部最优的选择,即贪⼼选择来达到。
第六章-贪心算法
![第六章-贪心算法](https://img.taocdn.com/s3/m/d9c8671a2a160b4e767f5acfa1c7aa00b52a9dbe.png)
//每堆牌的张数减去平均数
i:=1;j:=n;
while (a[i]=0) and (i<n) do inc(i);
//过滤左边的0
while (a[j]=0) and (j>1) do dec(j);
//过滤右边的0
while (i<j) do
begin
inc(a[i+1],a[i]); a[i]:=0; inc(step); inc(i); while (a[i]=0) and (i<j) do inc(i);
现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。 例如 N=4,4 堆纸牌数分别为: ① 9 ② 8 ③ 17 ④ 6
移动3次可达到目的: 从 ③ 取4张牌放到④(9 8 13 10)->从③取3张牌放到 ②(9 11 10 10)> 从②取1张牌放到①(10 10 10 10)。 【输入格式】 N(N 堆纸牌,1 <= N <= 100) A1 A2 … An (N 堆纸牌,每堆纸牌初始数,l<= Ai <=10000) 【输出格式】 所有堆均达到相等时的最少移动次数。 【样例输入】Playcard.in
输出n;
//删去串首可能产生的无用零
【例6】拦截导弹问题(NOIP1999) 某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统,但是这种拦
截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每 一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭,由 于该系统还在试用阶段。所以一套系统有可能不能拦截所有的导弹。
因此,贪心不能简单进行,而需要全面的考虑,最后得到证明。
【例3】排队打水问题
(完整版)4+四+贪心算法+习题参考答案
![(完整版)4+四+贪心算法+习题参考答案](https://img.taocdn.com/s3/m/66ef2ac3e87101f69f31956a.png)
第四章作业部分参考答案1 • 设有n个顾客同时等待一项服务。
顾客i需要的服务时间为t i,1 i n。
应该如何安排n个顾客的服务次序才能使总的等待时间达到最小?总的等待时间是各顾客等待服务的时间的总和。
试给出你的做法的理由(证明) 。
策略:对t i 1 i n进行排序,h t i2t i n,然后按照递增顺序依次服务i i」2,…,i n即可。
解析:设得到服务的顾客的顺序为j1, j2,..., j n ,则总等待时间为T (n 1)t j i (n 2)t j2 2.? 则在总等待时间T中切的权重最大,切的权重最小。
故让所需时间少的顾客先得到服务可以减少总等待时间。
证明:设t i1 t i2 t i n, ,下证明当按照不减顺序依次服务时,为最优策略。
记按照i1i2 i n 次序服务时,等待时间为T ,下证明任意互换两者的次序,T 都不减。
即假设互换i, j (i j) 两位顾客的次序,互换后等待总时间为T~,则有T T.由于T (n 1)t i1 (n 2)t i2 2t i n2 t,i n 1T (n 1)t i1 (n 2)t i2 (n i)t i i (n j)t i j 2t ti n 2 i n 1T (n 1)t i1 (n 2)t i2 (n i)t i j (n j)t i i 2t i t ii n 2 i n 1则有T~ T (j i)(t i j t i i ) 0.同理可证其它次序,都可以由i1i2 i n 经过有限次两两调换顺序后得到,而每次交换,总时间不减,从而i1i 2 i n 为最优策略2. 字符a ~h 出现的频率分布恰好是前 8个Fibo nacci 数,它们的Huffman编码是什么?将结果推广到n 个字符的频率分布恰好是前n 个Fibonacci 数的情 形。
Fib on acci 数的定义为:F o1,F i 1, F nF n 2 F n 1 if n 1所以a 的编码为:1111111 b 的编码为:1111110 c 的编码为:111110 d 的编码为:11110 e 的编码为:1110 f 的编码为:110 g 的编码为:10 h 的编码为:0 推广到 n 个字符:第 1 个字符: n-1 个 1 ,11 1n1 第 2 个字符: n-2 个1 , 1 个 0, 11 10n2第 3 个字符: n-3 个 1 ,1 个 0, 11 10n3第n-1个字符:1个1 , 1 个 0, 10 第 n 个字符: 1 个 03. 设 p 1,p 2, ,p n 是准备存放到长为 L 的磁带上的 n 个程序,程序 p i 需要的 n 带长为 a i 。
算法分析贪心算法习题
![算法分析贪心算法习题](https://img.taocdn.com/s3/m/4819e28e192e45361066f5ee.png)
如果一个游戏没能在规定期限前完成, 则要从奖励费m元中扣去一部分钱wi, wi为自然数。不同的游戏扣去的钱数是 不一样的。
问题描述
当然,每个游戏本身都很简单,保证每 个参赛者都能在一个时段内完成,而且 都必须从整时段开始。主持人只是想考 考每个参赛者如何安排组织自己做游戏 的顺序。
作为参赛者,小伟如何赢取最多的钱!
删数问题
通过键盘输入一个高精度的n(n≤240)位正整数N, 去掉其中任意s个数字后,剩下的数字按原左右次序 将组成一个新的正整数。编程对给定的n和s,寻找 一种方案,使得剩下的数字组成的新数最小。 输入:N
s 输出:最后剩下的最小数
样例输入:178543 S=4
样例输出:13
问题分析
由于正整数N的有效位数最大可达240 位,所以可以采用字符串类型来存储N
解题思路
这个题目思路很容易想,肯定是优先使 用半径大的喷水装置。因为半径越大的 喷水装置所能覆盖的范围就越大。
其实这个确定优先选择哪一个的过程就 是贪心选择的过程。
所以本题就是先对所有的喷水装置半径 排序,计算出,每个喷水装置所能覆盖 的长度。每次都选出当前半径最大的, 直到能覆盖完所有的草地。
智力大冲浪
【问题描述】 小伟报名参加电视台的智力大冲浪节目。本 次挑战赛吸引了众多参赛者,主持人为了表 彰大家的勇气,先奖励每个参赛者m元。先 不要太高兴!因为这些钱还不一定都是你的! 接下来,主持人宣布了比赛规则:
问题描述
首先,比赛时间分为n个时段,它又给 出了很多小游戏,每个小游戏都必须在 规定期限 ti 前完成(1<=ti<=n)。
贪心算法习题
排队接水
贪心算法题库
![贪心算法题库](https://img.taocdn.com/s3/m/f9e6622149d7c1c708a1284ac850ad02de80079b.png)
贪心算法是一种在每一步选择中都采取当前情况下的局部最优选择,并希望导致结果是全局最优解的算法。
下面是一些贪心算法的题目和解答:1. 旅行商问题(Travelling Salesman Problem):问题描述:给定一个城市列表和一个距离列表,要求找出一条路径,使得路径上的所有城市都经过,且总距离最短。
贪心算法解法:首先对城市按照距离进行排序,然后从最近的两个城市开始,每次都选择距离当前位置最近的两个城市,直到遍历完所有城市。
由于贪心算法每次选择的都是当前情况下的最优解,因此最终得到的路径总距离是最短的。
2. 背包问题(Knapsack Problem):问题描述:给定一组物品,每个物品都有自己的重量和价值,要求在不超过背包总重量的情况下,如何选择物品使得背包中物品的总价值最大。
贪心算法解法:按照物品的重量对物品进行排序,然后每次选择重量最小的物品,直到背包已满或无物品可选。
由于贪心算法每次选择的都是当前情况下的最优解,因此最终得到的方案总是可以找到一个大于等于当前最优解的方案。
3. 网格找零问题(Currency Change Problem):问题描述:给定一组面值不同的硬币,要求用最少的组合方式从一定金额中找零。
贪心算法解法:首先对硬币面值进行排序,然后每次使用当前面值最小的硬币进行组合,直到金额为零或无硬币可选。
贪心算法在此问题中的思路是每次选择最小的硬币进行使用,这样可以保证找零的最小数量。
以上题目和解答只是贪心算法的一部分应用,实际上贪心算法在许多其他领域也有广泛的应用,例如网页布局优化、任务调度、网络流等等。
贪心算法的优势在于其简单易懂、易于实现,但也有其局限性,例如无法处理一些存在冲突的情况或最优解不唯一的问题。
因此在实际应用中需要根据具体问题选择合适的算法。
汽车加油问题之贪心算法(全面分析)
![汽车加油问题之贪心算法(全面分析)](https://img.taocdn.com/s3/m/7bdb36f6a48da0116c175f0e7cd184254a351b71.png)
汽车加油问题之贪心算法(全面分析)一辆汽车加满油后可以行驶N千米。
旅途中有若干个加油站。
指出若要使沿途的加油次数最少,设计一个有效的算法,指出应在那些加油站停靠加油。
给出N,并以数组的形式给出加油站的个数及相邻距离,指出若要使沿途的加油次数最少,设计一个有效的算法,指出应在那些加油站停靠加油。
要求:算法执行的速度越快越好。
问题分析(前提行驶前车里加满油)对于这个问题我们有以下几种情况:设加油次数为k,每个加油站间距离为a[i];i=0,1,2,3……n1.始点到终点的距离小于N,则加油次数k=0;2.始点到终点的距离大于N,A 加油站间的距离相等,即a[i]=a[j]=L=N,则加油次数最少k=n;B 加油站间的距离相等,即a[i]=a[j]=L>N,则不可能到达终点;C 加油站间的距离相等,即a[i]=a[j]=L<N,则加油次数k=n/N(n%N==0)或k=[n/N] 1(n%N!=0);D 加油站间的距离不相等,即a[i]!=a[j],则加油次数k通过以下算法求解。
算法描述贪心算法的基本思想该题目求加油最少次数,即求最优解的问题,可分成几个步骤,一般来说,每个步骤的最优解不一定是整个问题的最优解,然而对于有些问题,局部贪心可以得到全局的最优解。
贪心算法将问题的求解过程看作是一系列选择,从问题的某一个初始解出发,向给定目标推进。
推进的每一阶段不是依据某一个固定的递推式,而是在每一个阶段都看上去是一个最优的决策(在一定的标准下)。
不断地将问题实例归纳为更小的相似的子问题,并期望做出的局部最优的选择产生一个全局得最优解。
由于汽车是由始向终点方向开的,我们最大的麻烦就是不知道在哪个加油站加油可以使我们既可以到达终点又可以使我们加油次数最少。
提出问题是解决的开始.为了着手解决遇到的困难,取得最优方案。
我们可以假设不到万不得已我们不加油,即除非我们油箱里的油不足以开到下一个加油站,我们才加一次油。
江西科学技术版小学信息技术五年级下册《主题活动:贪心算法》同步练习题附知识点归纳
![江西科学技术版小学信息技术五年级下册《主题活动:贪心算法》同步练习题附知识点归纳](https://img.taocdn.com/s3/m/217e6684d05abe23482fb4daa58da0116d171f0a.png)
江西科学技术版小学信息技术五年级下册《主题活动:贪心算法》同步练习题附知识点归纳一、课文知识点归纳:1. 贪心算法的基本概念:(1)贪心算法是一种求解最优解问题的更简单、更迅速的设计技术。
(2)它以当前情况为基础,根据某个优化测度做出最优选择,而不考虑所有可能的整体情况。
(3)贪心算法通过自顶向下、迭代的方法做出相继的贪心选择,每做一次选择,问题就简化为一个规模更小的子问题。
2. 贪心算法的基本要素:(1)贪心选择性质:整体最优解可通过一系列局部最优解的选择达到,且每次选择不依赖于后续选择。
(2)最优子结构性质:问题的最优解包含其子问题的最优解。
3.贪心算法的步骤:(1)建立数学模型来描述问题。
(2)把求解的问题分成若干个子问题。
(3)对每个子问题求解,得到子问题的局部最优解。
(4)将子问题的局部最优解合成原问题的解。
4.贪心算法的特点:(1)简单易实现,计算效率高。
(2)适用于具有贪心选择性质和最优子结构性质的问题。
(3)得到的解通常是某种意义上的局部最优解,但不一定是全局最优解。
5.贪心算法的应用场景:(1)货币兑换问题(如找零钱问题)。
(2)背包问题(在限制条件下选择最大价值的物品)。
(3)活动选择问题(安排一系列活动使得尽可能多的活动被安排)。
二、同步练习题。
(一)、填空题。
1. 贪心算法是一种在每一步选择中都采取在当前状态下最好或最优__________的选择,从而希望导致结果是全局最好或最优的算法。
2. 在解决背包问题时,如果背包容量为20千克,物品A重5千克价值100元,物品B重10千克价值150元,为了价值最大化,应先放入____________千克的物品。
3. 在活动选择问题中,若有多个活动的时间区间存在冲突,我们通常使用____________算法进行筛选。
(二)、选择题。
1. 下列关于贪心算法的说法,正确的是()。
A. 贪心算法总是能得到全局最优解B. 贪心算法是一种启发式搜索算法C. 贪心算法只适用于特定类型的问题D. 贪心算法不需要考虑问题的整体结构2. 在教室调度问题中,若某间教室在某天的课程安排如下:课程A 9:00-10:00,课程B 9:30-10:30,课程C 10:30-11:30,则能在这间教室连续进行的课程是()。
c++贪心算法经典例题
![c++贪心算法经典例题](https://img.taocdn.com/s3/m/bf72c348f68a6529647d27284b73f242336c319c.png)
c++贪心算法经典例题和详解贪心算法(Greedy Algorithm)是一种优化问题解决方法,其基本思想是每一步都选择当前状态下的最优解,以期望达到全局最优解。
贪心算法的特点是每一步都要做出一个局部最优的选择,而这些局部最优选择最终构成了全局最优解。
下面是一个经典的贪心算法例题以及详解:例题:活动选择问题(Activity Selection Problem)假设有一个需要在同一时段使用同一个资源的活动集合,每个活动都有一个开始时间和结束时间。
设计一个算法,使得能够安排最多数量的互不相交的活动。
# 输入:-活动的开始时间数组`start[]`。
-活动的结束时间数组`end[]`。
# 输出:-选择的互不相交的活动的最大数量。
# 算法详解:1. 首先,将活动按照结束时间从小到大排序。
2. 选择第一个活动,并将其加入最终选择的集合中。
3. 对于剩下的活动,选择下一个结束时间最早且与前一个活动不冲突的活动。
4. 重复步骤3,直到所有活动都被选择。
```cpp#include <iostream>#include <algorithm>#include <vector>using namespace std;// 定义活动结构体struct Activity {int start, end;};// 比较函数,用于排序bool compareActivities(Activity a, Activity b) {return a.end < b.end;}// 贪心算法解决活动选择问题void activitySelection(vector<Activity>& activities) {// 按照结束时间排序sort(activities.begin(), activities.end(), compareActivities);// 第一个活动总是被选中cout << "Selected activity: (" << activities[0].start << ", " << activities[0].end << ")" << endl;// 选择其余活动int lastSelected = 0;for (int i = 1; i < activities.size(); i++) {// 如果当前活动的开始时间大于等于上一个选择的活动的结束时间,则选择该活动if (activities[i].start >= activities[lastSelected].end) {cout << "Selected activity: (" << activities[i].start << ", " << activities[i].end << ")" << endl;lastSelected = i;}}}int main() {vector<Activity> activities = {{1, 2}, {3, 4}, {0, 6}, {5, 7}, {8, 9}, {5, 9}};cout << "Activities before sorting:" << endl;for (const Activity& activity : activities) {cout << "(" << activity.start << ", " << activity.end << ") ";}cout << endl;activitySelection(activities);return 0;}```在这个例子中,我们首先定义了一个活动的结构体`Activity`,然后编写了一个比较函数`compareActivities` 用于排序。
c++贪心算法经典例题
![c++贪心算法经典例题](https://img.taocdn.com/s3/m/8bf7d55253d380eb6294dd88d0d233d4b14e3f8c.png)
c++贪心算法经典例题(原创实用版)目录一、贪心算法的基本概念与特点二、贪心算法的经典例题1.背包问题2.带有期限的作业排序3.最小生成树4.单源点最短路径三、贪心算法的应用场景与策略选择四、贪心算法的优缺点及注意事项五、总结正文一、贪心算法的基本概念与特点贪心算法是一种求解最优化问题的方法,其主要特点是在每一步都做出当前看来最好的选择,从而希望导致结果是全局最好的解。
贪心算法不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。
贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择。
二、贪心算法的经典例题1.背包问题:给定一组物品,每种物品都有一定的价值和重量,要求在限定的总重量内,选取若干物品放入背包,使得背包中物品的总价值最大。
2.带有期限的作业排序:给定一组作业,每项作业有固定的执行时间和期限,要求在期限内尽可能多地完成作业,使得完成作业的总时间最小。
3.最小生成树:给定一个无向连通图,要求找出一棵包含所有顶点且边权值之和最小的生成树。
4.单源点最短路径:给定一个有权值边的无向图,要求找出从指定源点到其他所有顶点的最短路径。
三、贪心算法的应用场景与策略选择贪心算法适用于问题能够分解成子问题来解决的情况,子问题的解可以相互独立地求得。
在贪心算法的应用过程中,需要仔细分析问题的特点,选择合适的贪心策略。
贪心策略的选择必须满足无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。
四、贪心算法的优缺点及注意事项贪心算法的优点是简单易懂、代码实现简单,且在许多情况下能够得到整体最优解。
缺点是贪心算法并不适用于所有问题,对于一些具有特殊性质的问题,可能无法得到最优解。
在使用贪心算法时,需要注意贪心策略的选择,避免因为贪心策略不合适而导致解的不正确。
五、总结贪心算法是一种求解最优化问题的方法,其关键在于选择合适的贪心策略。
贪心算法适用于问题能够分解成子问题来解决的情况,能够快速得到满意的解。
谈贪心算法
![谈贪心算法](https://img.taocdn.com/s3/m/9feaaabeb52acfc789ebc9ee.png)
谈谈贪心算法例1. 背包问题【题目描述】这是一大家很熟悉的背包问题。
给定n 种货物和一个载重量为m 的背包。
已知第i 种货物的重量为wi ,其总价值为pi ,编程确定一个装货方案,使得装入背包中货物的总价值最大。
输出此总价值和装货方案。
【算法分析】0,1 背包问题对每种物品只有两种选择:选和不选,可用动态规划解决。
而背包问题,可以选择物品的一部分装载,这样就可以把背包装满,用贪心算法可求得最优解。
采用贪心标准是:选择单位重量价值高的货物优先装入,这样才能保证背包中所装货物总价值最大。
而0,1 背包用贪心算法却不能得到整体最优,为什么呢?我们来看一个例子:有一背包容量为50 千克,有三种货物:物品 1 重10 千克;价值60 元;物品 2 重20 千克,价值100 元;物品 3 重30 千克;价值120 元。
总价值:(用贪心算法) 80+100+60=240 对于 0,1 背包问题, 贪心选择之所以不能得到最优解是因为它无法保证最终将背包装满,部分背包的 闲置使单位 重量背包空间的价值降低例 2 .排队问题【题目描述】在一个医院 B 超室,有 n 个人要做不同身体部位的 B 超, 已知每个人需要处理的时间为 ti ,( 0<i<=n ),请求出一种排列次序, 使每个人排队等候时间总和最小。
输入数据:第 1 行一个正整数 n (你<=10000 》,第 2 行有 n个不超过 1000 的正整数 ti.202010输出要求:n 个人排队时间最小总和。
输入输出样例输入:45 10 8 7输出:67【算法分析】本题贪心算法:n 个人时间从小到大排序,就是这n 个人最佳排队方案。
求部分和的和即为所求。
反证法证明:假设有最优解序列:s1,s2 ⋯sn, 如s1 不是最小的Tmin ,不妨设sk=Tmin, 将s1 与sk 对调,显然,对sk 之后的人无影响,对sk 之前的人等待都减少了,(s1-sk)>0, 从而新的序列比原最优序列好,这与假设矛盾,故s1 为最小时间,同理可证s2 ⋯sn 依次最小。
贪心算法例题简单说明
![贪心算法例题简单说明](https://img.taocdn.com/s3/m/d0dd7f54bf23482fb4daa58da0116c175f0e1e42.png)
贪⼼算法例题简单说明
1.选择不相交区间问题
贪⼼思路:按照结束时间的顺序排序,结束时间越早,后⾯就能放越多的事。
2.区间选点问题
贪⼼思路:从前往后扫每个区间的树⽊,数⽬的那个区间,从后往前种树。
3.区间覆盖问题
贪⼼思路:预处理完了之后,要找到右端点坐标最⼤的⼀个,直到到边。
这⾥我就要说⼀下了⼀定要注意上下的边界问题:
1.两个圆相切肯定不对,覆盖不全
2.覆盖圆与边相切也不对,覆盖不全
4.流⽔作业调度问题
贪⼼思路:
5.带期限和带罚款的单位时间任务调度
贪⼼思路:罚款越⼤,越要完成,所以罚款⼤的要先处理,将罚款⼤的放在能放区间的最后。
贪心算法详解(C++版)
![贪心算法详解(C++版)](https://img.taocdn.com/s3/m/427ced750029bd64793e2c80.png)
3-1 】删数问题【问题描述】键盘输入一个高精度的正整数n( n<=240 位) ,去掉其中任意s 个数字后剩下的数字按原左右顺序将组成一个新的正整数。
编程对给定的n 和s,寻找一种方案,使得剩下的数字组成的数最小。
输入:NS输出:最后剩下的最小数。
【样例输入】1785434【样例输出】13【题解】由于正整数n 的有效位数为240 位,所以很自然地采用字符串类型存储n。
那么如何解决哪s 位被删呢?是不是最大的s 个数字呢?为了尽可能的逼近目标,我们选取的贪心策略为:每一步总是选择一个使剩下数最小的数字删去。
即按高位到低位的顺序搜索,若各位数字递增,则删去最后一个数字;否则删去第一个递减区间的首字符,这样删一位便形成了一个新数字串。
然后回到串首,按上述规则再删下一个数字。
重复以上过程s次为止,剩下的字串便是问题的解了。
【标程】#include <iostream>#include <cstdio>#include <cstring>using namespace std;char a[100001];int main(){int n,i,j,l,k;gets(a);cin>>n;l=strlen(a);for(i=1;i<=n;i++){for(j=0;j<l-1;j++)if(a[j]>a[j+1]) {for(k=j;k<l-1;k++)a[k]=a[k+1]; break;}l--;}for(i=0;i<l-1;i++){if(a[i]!='0'){k=i;break;}}for(j=i;j<=l-1;j++) cout<<a[j];cout<<endl;return 0;}【例3-2】取数游戏【问题描述】给出2n(n<=100)个自然数(数小于等于30000)。
贪心算法经典例题
![贪心算法经典例题](https://img.taocdn.com/s3/m/bed6eca64bfe04a1b0717fd5360cba1aa8118cb5.png)
贪心算法经典例题贪心算法是一种求解最优问题的算法思想,其核心理念是每一步都选择当前最优的策略,从而达到全局最优解。
贪心算法可以应用于许多经典问题,下面将介绍几个常见的贪心算法经典例题及相关参考内容。
1. 会议室安排问题题目描述:给定一组会议的开始时间和结束时间,求解如何安排会议,使得尽可能多的会议可以在同一时间段内进行。
解题思路:贪心算法可以通过每次选择结束时间最早的会议来求解。
首先将会议按照结束时间排序,选择第一个会议作为首先安排的会议,然后依次选择后续结束时间不冲突的会议进行安排。
相关参考内容:- 《算法导论》第16章:贪心算法(ISBN: 9787115265955)- 《数据结构与算法分析》第13章:贪心算法(ISBN: 9787302483626)2. 零钱兑换问题题目描述:给定一定面额的硬币,求解如何用最少的硬币数量兑换指定金额的零钱。
解题思路:贪心算法可以通过每次选择面额最大且不超过目标金额的硬币来求解。
从面额最大的硬币开始,尽可能多地选择当前面额的硬币,并减去已经选择的硬币金额,直到金额为0。
相关参考内容:- 《算法导论》第16章:贪心算法(ISBN: 9787115265955)- 《算法4》第1章:基础(ISBN: 9787302444627)3. 区间调度问题题目描述:给定一组区间,求解如何选择尽可能多的不重叠区间。
解题思路:贪心算法可以通过每次选择结束时间最早的区间来求解。
首先将区间按照结束时间排序,选择第一个区间作为首先选择的区间,然后依次选择后续结束时间不与已经选择的区间重叠的区间进行选择。
相关参考内容:- 《算法导论》第16章:贪心算法(ISBN: 9787115265955)- 《数据结构与算法分析》第13章:贪心算法(ISBN: 9787302483626)4. 分糖果问题题目描述:给定一组孩子和一组糖果,求解如何分配糖果,使得最多的孩子能够得到满足。
解题思路:贪心算法可以通过每次选择糖果最小且能满足当前孩子的糖果来求解。
贪心算法
![贪心算法](https://img.taocdn.com/s3/m/cebb8523dd36a32d73758103.png)
贪心算法专题实例解析【例1】删数问题Description键盘输人一个高精度的正整数N(<=240位),去掉其中任意s个数字后剩下的数字按原左右次序将组成一个新的正整数.编程对给定的N和s,寻找一种方案使得剩下的数字组成的新数最小。
InputnsOutput最后剩下的最小数【例2】取数游戏Description给出2n(n<=100)个自然数(数小于等于30000)。
游戏双方分别为A方(计算机方)和B方(对弈的人)。
只允许从数列两头取数。
A先取,然后双方依次轮流取数。
取完时,谁取的数字总和最大为取胜方;若双方和相等,属于A胜。
试问A方是否有必胜的策略。
Input键盘输入N和2*N个自然数Output共3N+2行,其中前3*N行为游戏经过。
每3行分别为A方所取的数和B方所取的数及B方取数前应给予的适当提示,让游戏者选择哪一头的数(L/R----左端或右端)。
最后2行分别为A方取得的数和裕B方取得的数和。
【例3】0/1背包问题Description给定一个载重量为weight的背包,n个物品,其重量分别为w[i],价值分别为p[i],1<=i<=n,物体或者被装入背包,或者不被装入背包,只有两种选择。
要求把物品装入背包,并使包内物品价值最大。
Sample Input11 {weight}4 {n}2 4 6 7 {w[i]}6 10 12 13 {p[i]}Sample Output0 1 0 123【例4】活动选择Description假设有一个需要使用某一资源的n个活动组成的集合是,s{1,2,…,n}。
该资源一次只能被一个活动所占用,每个活动有一个开始时间b[i]和结束时间e[i] (b[i]<e[i])。
若b[i]>=e[j]或b[j]>=e[i],则活动i和活动j兼容。
我们的任务是:选择由互相兼容的活动组成的最大集合。
Input (in.tzt)NB[1] e[1]…………B[n] e[n]Output (out.txt)共两行,第一行为满足要求的活动占用的时间t,第2行为最大集合中的活动序号,每个数据之间用一个空格隔开。
2010年8月19日贪心法例题讲解
![2010年8月19日贪心法例题讲解](https://img.taocdn.com/s3/m/d3b11719227916888486d76c.png)
旅行家的预算(acm)旅行家的预算Problem description一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。
给定两个城市之间的距离D1、汽车油箱的容量C(以升为单位).每升汽油能行驶的距离D2、出发点每升汽油价格P和沿途油站数N(N可以为零),油站i离出发点的距Di、每升汽油价格 Pi( i=l,2,...N)。
计算结果四舍五入至小数点后两位。
如果无法到达目的地,则输出“No solution”。
Input输入数据的第一行是四个实数;D1 C D2 P分别表示两个城市之间的距离,汽车油箱的容量,每升汽油能行驶的距离,出发点每升汽油格;第二行是一个整数N,沿途的油站数。
第三行到第N+2,每一行是一个油站的基本信息描述,包括该油站离出发点的距离,该油站每升汽油的格。
Output输出到达目的城市的最小费用(四舍五入到两位小数),若不能到达目的城市则输出 No solutionSample Input275.6 11.9 27.4 2.82102.0 2.9220.0 2.2Sample Output26.95Problem Source// 测试用例275.6 11.9 17.4 2.82102.0 2.9220.0 2.2142.54//275.6 11.9 10.4 2.83102.0 2.1160.2 2.3220.0 2.262.99分析:需要考虑如下问题:1)出发前汽车的油箱是空的,故汽车必须在起点(1号站)处加油。
加多少油?2)汽车行程到第几站开始加油,加多少油?可以看出,原问题需要解决的是在哪些油站加油和加多少油的问题。
对于某个油站,汽车加油后到达下一加油站,可以归结为原问题的子问题。
因此,原问题关键在于如何确定下一个加油站。
通过分析,我们可以选择这样的贪心标准:对于加油站I,下一个加油站J可能第一个是比油站I油价便宜的油站,若不能到达这样的油站,则至少需要到达下一个油站后,继续进行考虑。
贪心算法-例题讲解
![贪心算法-例题讲解](https://img.taocdn.com/s3/m/c0f1040eb6360b4c2e3f5727a5e9856a56122647.png)
贪⼼算法-例题讲解前⾔:此博客在写作过程中参考了⼤量资料和博客,不能⼀⼀列举,还请见谅。
概述贪⼼法:从问题的某⼀个初始状态出发,逐步构造最优解从⽽向⽬标前进,并期望通过这种⽅法产⽣出⼀个全局最优解的⽅法贪⼼是⼀种解题策略,也是⼀种解题思想,⽽不是算法贪⼼策略与其他算法的区别贪⼼与递推:贪⼼法推进每⼀步不依据某⼀固定的递推式,⽽是当前看似最佳的贪⼼决策,不断的将问题归纳为更加⼩的相似的⼦问题贪⼼与动态规划:贪⼼是“⿏⽬⼨光”;动态规划是“统揽全局”贪⼼法的优缺点优点:思维复杂度低、代码量⼩、运⾏效率⾼、空间复杂度低等缺点:很难找到⼀个简单可⾏并且保证正确的贪⼼思路贪⼼算法的应⽤贪⼼算法的常⽤范围有明显的贪⼼可证明贪⼼策略的贪⼼(最常见的)贪⼼数据结构:堆/Kruskal/Prim/Dijkstra博弈/游戏策略,这些策略⼤多是贪⼼求较优解或多次逼近求最优解⼏个简单的贪⼼例⼦最优装载问题:给n个物体,第i个物体重量为wi,选择尽量多的物体,使得总重量不超过C贪⼼策略:先拿轻的部分背包问题:有n个物体,第i个物体的重量为wi,价值为vi,在总重量不超过C的情况下让总价值尽量⾼。
每⼀个物体可以只取⾛⼀部分,价值和重量按⽐例计算贪⼼策略:先拿性价⽐⾼的乘船问题:有n个⼈,第i个⼈重量为wi。
每艘船的载重量均为C,最多乘两个⼈。
⽤最少的船装载所有⼈贪⼼策略:最轻的⼈和最重的⼈配对例题(基础)1.删数问题-【问题描述】键盘输⼊⼀个⾼精度的正整数n(n<=240位),去掉其中任意s个数字后剩下的数字按照原来的次序将组成⼀个新的正整数。
编程对给定的n和s,寻求⼀种⽅案,使得剩下组成的新数最⼩。
贪⼼策略为:每⼀步总是选择⼀个使剩下的数最⼩的数字删去,即按⾼位到低位的顺序搜索,若各位数字递增,则删除最后⼀个数字,否则删除第⼀个递减区间的⾸字符。
然后回到串⾸,按上述规则再删除下⼀个数字。
重复以上过程s次,剩下的数字串便是问题的解了。
贪心算法例题
![贪心算法例题](https://img.taocdn.com/s3/m/0661062ef4335a8102d276a20029bd64783e62c7.png)
贪心算法例题
贪心算法是一种在每一步选择中都采取当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法。
以下是一个贪心算法的例子:
问题描述:有100个人在一酒吧,一次酒局中大家都决定向其他每个人敬酒,但只有距离较近的人之间才能互敬。
酒局结束后,每人都记录下他们之间互敬了多少次。
现给出所有人的互敬次数,找出互敬次数最多的那个人。
贪心策略:从最多互敬次数的人开始,每次都选择能互敬次数最多的人,直到达到最大互敬次数为止。
具体实现:
1. 首先将所有人的互敬次数存入一个数组中。
2. 从数组中找到互敬次数最多的人,假设其互敬次数为max_times。
3. 从数组中删除所有互敬次数小于max_times的人,因为他们的互敬次数已经确定不会超过max_times。
4. 重复步骤2和3,直到数组为空。
这个贪心算法的例子中,每次选择都是基于当前情况下的最优选择,希望通过这种方式达到全局最优的结果。
贪心算法详解(C++版)
![贪心算法详解(C++版)](https://img.taocdn.com/s3/m/1358849ebceb19e8b8f6baa2.png)
2————活动2兼容(持续时间1—4),加入S,S={2},t=4
1不兼容,放弃
5不兼容,放弃
8————活动8兼容(持续时间5—7),加入S,S={2,8},t=7
9不兼容,放弃
10不兼容,放弃
7不兼容,放弃
6————活动6兼容(持续时间8—11),加入S,S={2,8,6},t=11
struct stu
首先将递增序列的活动1进入集合S。然后依次分析递增序列中的活动2,活动3,……,活动n,每次将与S中的活动兼容的活动加入到集合S中。
我们结合问题的样例输入,先将11个活动的活动号、开始时间、结束时间及递增编号表
按照以上这种贪心策略,贪心选择如下:
时间0 1 2 3 4 5 6 7 8 9 11 12 13 14
{
for(j=0;j<l-1;j++)if(a[j]>a[j+1])
{
for(k=j;k<l-1;k++)a[k]=a[k+1];
break;
}
l--;
}
for(i=0;i<l-1;i++)
{
if(a[i]!='0')
{
k=i;
break;
}
}
for(j=i;j<=l-1;j++) cout<<a[j];
4不兼容,放弃
11不兼容,放弃
3————活动3兼容(持续时间12—14),加入S,S={2,8,6,3},t=14
所以问题的解:t=14,S={2,8,6,3}。
【标程】
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1. 背包问题定义如下:
输入:正数M W W W P P P n n ;,...,
,;,...,,2121 输出:10,,...,,21≤≤i n X X X X ,使得:∑≤≤n
i i i X P 1最大;
∑≤≤≤n
i i
i
M X
W 1
给出一个求解背包问题的贪心算法,并证明其正确性。
解:
贪心思想:首先计算每种物品单位重量的价值
i
i
W P ,并进行由大到小的排序,然后依据贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包,若将这种物品全部装入背包后,背包内的物品总重量未超出M ,则选择单位重量价值次高的物品,以此类推,每次都是选择当前未放入背包的单位重量价值最高的物品,直到总重量大于或等于M 。
优化子结构:设A 是此背包问题的优化解,且A 包含物品j ,其中j 的重量为w ,则A ’=A-{j X }是剩余的n-1个原重物品1,2,…,j-1,j+1,n 以及重为w w j -的物品j 中可装入容量为M-w 的背包问题的优化解。
证明:利用反证法。
假设A ’不是该子问题的优化解,则存在B ’是该子问题的优化解,由此可知B'的价值大于A'的价值,令B=B'+{j X },则B 的价值大于A 的价值,这与A 是此问题的优化解相矛盾。
所以此问题具有优化子结构。
贪心选择性:计算每种物品单位重量的价值
i
i
W P ,并进行由大到小的排序。
若
11,1
1-≤≤≥++n i W P
W P i i i i ,则存在背包问题的一个最优解使得}1,min{1
1W M
X =。
证明:设A 是一个优化解,设其第一个物品的选择为1X
(1)如果}1,min{1
1W M
X =,则命题成立。
(2)如果}1,min{11W M
X ≠,则X1在全部放入背包总价值不会超过M 的情况下,
并没有全部放入,设B 满足}1,min{1
1W M
X =,i X (i=2,3,...,n)与A 相同,且调
整最终的价值不会超过M ,则B 是一个优化解且满足}1,min{1
1W M
X =
正确性证明:
因为算法处理过程按照最有子结构和贪心选择性依次处理背包问题,则此算法具有正确性。
2. 写出分支界限的一般算法。
(利用爬山算法)
解:
1) 构造由根组成的单元素栈S ,根节点的权值初始化为0; 2) 将可行解初始化为cost=∞;
3) 计算当前栈顶的权值=父节点的权值+该扩展分支的权值; 4 ) If Top(S)是目标节点
then 根据该节点计算当前可行解cost ,cost=新的可行解;
5 ) If 当前栈顶Top(S)的cost ’>cost ,则Pop(S),且不再将其子节点入栈; 6) 将S 的子节点按照其启发式测度由大到小的顺序压入S ; 7) If S 空且cost=∞,then 失败; 8 ) If S 空且 cost!=∞,return cost; 9 ) Else goto 3.
3. kn n k k J P J P J P →→→,...,,2211是一个可能解,
当且仅当kn k k J J J ,...,,21必是一个拓扑序列。
证明:=>kn n k k J P J P J P →→→,...,,2211是一个可能解,
而每个人的工作能力符合关系n P P P <
<<...,21,则对于j i n j i <∈∀其中整数],,1[,,若kj ki J J 与满足偏序关系,则有kj ki J J <;若不满足偏序关系,则kj ki J J 与的分配无所谓顺序,所以,kn k k J J J ,...,,21必是一个拓扑序列;
<=kn k k J J J ,...,,21是一个拓扑序列,对于j i n j i <∈∀其中整数],,1[,,若
kj ki J J 与满足偏序关系,则有kj ki J J <,其分配满足j i P P <;若不满足偏序关系,则kj ki J J 与的分配无所谓顺序,不妨使得分配情况满足j i P P <,于是将所有的工作分配完成之后,使得n P P P <<<...,21成立,则kn n k k J P J P J P →→→,...,,2211是一个分配任务的可能解。
4. 修改拓扑排序算法,写出严格的分支界限算法。
(使用爬山法)
解:
1) 生成树根root ,其权值为解代价下界; 2) 将可行解的代价初始化为cost=∞;
3) 选择偏序集中没有前序元素的所有元素,根据加工后的代价矩阵元素,按权
值由大到小依次入栈,作为root的子节点;
4) For root的每个子节点v,其权值为加工后的代价矩阵元素加其父节点权值;
5) 如果此节点为目标节点,且权值不大于cost,则令cost=当前节点的权值,作为界限;
6) 如果此节点权值大于cost,则将此分支剪掉,其子节点不再入栈;
7 ) S=S-{v};
8) 把v作为根,递归地处理S.
5. 给出求解旅行商问题的详细算法。
解:
1) 根据各边之间的权值,列出此问题的初始代价矩阵;
2) 将代价矩阵进行处理,每行(列)减去减去该行(列)的最小值,使得每行(列)
至少有一个零,其余各元素非负,每行(列)所减去所有数的和即为解的代价下界;
3) 选择满足下列条件的边(i,j),使得
=,0
Cost∈
)
∀
j
Cost,所有包含(i,j)的解集合作为
i
,(=
i
Cost
|)1,
}
max{
(
)1,(V
k
k
左子树,所有不包含(i,j)的解集合作为右子树;
4) 左子树的代价下界不变,计算右子树的代价:分别从变换后的代价矩阵的
第i行第j 列中找到具有最小代价的从i出发的边(i,k)和进入j边(r,j),将这两条边的代价与其父节点的解的代价下界求和,即为右子树节点的代价下界;
5) 构造左子树根对应的代价矩阵:矩阵中的第i行第j 列应该被删除,并且
代价矩阵的(j,i)元素的位置应该被置为∞;
6) 计算左子树的代价下界:此时左子树的代价矩阵中可能出现某行或某列没
有0的情况,则需相应的减去一个对应行或列的最小数,于是可以获得左子树的新代价下界;
7) 构造右子树根对应的代价矩阵:把代价矩阵的(j,i)元素的位置置为∞;
8) 计算右子树的代价下界:此时右子树的代价矩阵中可能出现某行或某列没
有0的情况,则需相应的减去一个对应行或列的最小数,于是可以获得右子树的新代价下界;
9) 继续利用爬山策略处理,对当前的左右子树中分别递归处理,当处理涉及
到n个顶点时则检验是否已经构成环,若是,则成功返回。