4+四+贪心算法+习题参考答案
贪心算法求解问题(优化版)
贪心算法求解问题问题分析:此问题为程序最优存储问题,问题要求最后存储的两个磁带上的长度差异就最小。
若在最优解中去掉i个程序段,显然在(n-i)个程序段的存储中应仍是最优解,因为此问题存在最优子结构。
另外,由于每个程序的长度不同,每将一个程序存储到A或者B(用A和B来表示两个磁带上存储程序的集合)后,显然还与后续怎么存储程序有关,即当前结果依赖子问题的结果。
这正是动态规划算法的基本特征,而贪心算法仅在当前状态下做出最好选择,然后再去做子问题的局部最优解最终就是问题的最优解,贪心算法不依赖于将来所做的子问题的解,显示,此问题是一个动态规划问题,是一个0-1背包问题。
虽然对有些问题,贪心算法并不能得到一个最优解,但往往能快速地得到一个近似最优解。
下面就来讨论如何用贪心算法得到近似最优解。
贪心算法思路为了使最后两个磁带的长度差异越小,就先将长度较大的程序优先放入到磁带(此处用A和B分别表示两个磁带)上。
因此排序选择递减排序。
用p[ ]数组来存放第i个程序长度为p[i-1],首先将其按程序长度大小递减的顺序排序,将排好序的各程序下标记录到与与p[]等长的数组a[ ]中。
然后再根据a[]中记录的下标找到相应的程序p[a[i]]放到A或者B 中。
现在就接下就是如何存放来达到近似最优解的问题了开始A和B中没有任何元素(本程序中采用vector动态定义A,B),如果用sumA和sumB来标记A和B中已存入程序的总长度,在存入当前最优解时,先比较sumA和sumB 的大小,将最优解存入到程序总长度较短的那个程序集合,如果长度一样,则存入到A或者B中(本程序是存入到A集合中),可以看到这样存入的话,就会尽量减小A和B长度的差异,从而尽量接近最优存储得到近似最优解之前提交的贪心算法的思想是直接交叉存入到A和B中,那样得到的解在一定程度能得利近似最优解,那种思想只对程序段长度相差小的情况有比较好的结果,因为那种思想大概是将程序段平均到A和B中,在很多情况下不能得到近似最优解。
第4章贪心算法习题(免费阅读)
算法实现题4-5 程序存储问题
数据输入:
第一行是2 个正整数,分别表示文件个数n和磁带的长 度L。接下来的1 行中,有n个正整数,表示程序存放在磁 带上的长度。
结果输出: 最多可以存储的程序数。
输入示例
6 50
2 3 13 8 80 20 输出示例
5
i 012345
x 2 3 13 8 80 20 7
3
算法实现题4-5 程序存储问题
问题描述: 设有n 个程序{1,2,…, n }要存放在长度为L的磁带上。
程序i存放在磁带上的长度是 li,1 ≤ i ≤ n。 程序存储问题要求确定这n 个程序在磁带上的一个
存储方案,使得能够在磁带上存储尽可能多的程序。 编程任务:
对于给定的n个程序存放在磁带上的长度,编程计 算磁带上最多可以存储的程序数。
532.00
10
算法实现题4-6 最优服务次序问题
double greedy( vector<int> x) {
int i,n=x.size(); sort(x.begin(),x.end()); for(i=1;i<n;++i)
x[i] += x[i-1]; double t=0; for(i=0;i<n;++i) t+=x[i]; t /= n;
算法实现题4-5 程序存储问题
int greedy( vector<int> x, int m){
int i=0, sum=0, n=x.size();
sort(x.begin(),x.end());
while(i
if(sum <= m) i++;
第4章-贪心算法-习题
算法实现题4-15 套汇问题
while(1){
cin >> n;
if(n == 0) break;
//输入结束
for(i=0; i < n; ++i) cin >> name[i];
数据输入
第1行有2个正整数n和k,表示汽车加满油后可行驶nkm, 且旅途有k个加油站。接下来的一行中,有k+1个整数,表示 第k个加油站与第k-1个加油站之间的距离。第0个加油站表 示出发地,汽车已加满油。第k+1个加油站表示目的地。
结果输出
计算出的最少加油次数。如果无法到达目的地,则输 出”No Solution”。
3
算法实现题4-5 程序存储问题
问题描述: 设有n 个程序{1,2,…, n }要存放在长度为L的磁带上。
程序i存放在磁带上的长度是 li,1 ≤ i ≤ n。 程序存储问题要求确定这n 个程序在磁带上的一个
存储方案,使得能够在磁带上存储尽可能多的程序。 编程任务:
对于给定的n个程序存放在磁带上的长度,编程计 算磁带上最多可以存储的程序数。
定义:
vector<int> x; 读取数据:
int n; scanf(“%d”, &n); int temp; for (int i=0; i<n; i++){
scanf(“%d”, &temp); x.push_back(temp); }
return t;
}
i 01234567 8 9
x 1 12 33 55 56 99 99 234 812 1000
输入示例 77
输出示例 4
1 2 3 4 5 1 6 6 加油站数
4-4贪心-Dijkstra算法
邹娟-中国大学MOOC单源最短路径给定一个图G = (V , E),其中每条边的权是一个非负实数。
另外给定V 中的一个顶点v ,称为源。
求从源v 到所有其它各个顶点的最短路径。
单源最短路径问题的贪心选择策略:选择从源v 出发目前用最短的路径所到达的顶点,这就是目前的局部最优解。
单源最短路径的贪心算法基本思想:首先设置一个集合S;用数组dis[]来记录v到S中各点的目前最短路径长度。
然后不断地用贪心选择来扩充这个集合,并同时记录或修订数组dis[];直至S包含所有V中顶点。
单源最短路径的贪心算法一个顶点u 属于S 当且仅当从v 到u 的最短路径长度已知。
贪心选择:初始化:S 中仅含有源v 。
Dijkstra 算法Dijkstra 算法的做法是:(1)由近到远逐步计算,每次最近的顶点的距离就是它的最短路径长度。
(2)然后再从这个最近者出发。
即依据最近者修订到各顶点的距离,然后再选出新的最近者。
(3)如此走下去,直到所有顶点都走到。
Dijkstra 算法Procedure Dijkstra {S:={1}; //初始化Sfor i:= 2 to n do //初始化Ddis[i] =C[1, i] ; //初始时为源到顶点i一步的距离for i:=1 to n-1 do {从V-S中选取一个顶点u使得dis[u]最小;将u加入到S中;//将新的最近者加入Sfor w∈V-S do //依据最近者u修订dis[v]dis[w] := min(dis[w] , dis[u]+C[u ,w)}}Dijkstra 算法举例迭代S u dis[2] dis[3] dis[4] dis[5]初始{1} --10∞ 30 1001 {1,2} 2 10 60 301002 {1,2,4} 4 10 5030 903 {1,2,4,3} 3 10 50 30 604 {1,2,4,3,5} 5 10 50 30 603102050100301060由数组D[i]可知:从顶点1到顶点2、3、4、5的最短通路的长度分别为10、50、30和60。
(完整版)4+四+贪心算法+习题参考答案
第四章作业部分参考答案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 。
4-贪心算法
二、TSP问题的贪心算法
min ci
i 1 n
从驻地城市开始,每次选择还没到的最近(费用最少)的城市去.
1 2 7
1 4 4
2 4 1
7 4 1
5 3 2 3
5
3
2
3
1
2
5
3
4
Cost=1+3+2+1+7=14
1
2
5
4
3
Cost=1+3+3+1+2=10
template <class Type> Type GreedyTSP(Type **C,int n,int k,int x[ ]){ //从城市k出发用贪心算法求解TSP问题. //最佳解放在x[ ]里,路程(费用)用函数值返回 x[1]=k; int u=k; Type cost=0; for(int i=2; i<=n;i++){ Type min=; int v=0; for(int j=1; j<=n;j++) if(C[u][j]<min){min= C[u][j]; v=j;} cost+= min;x[i]=v; C[v][u]= ;u=v; } cost+=C[u][k]; return cost; }
§4.5 最小生成树
一、最小生成树
设G=(V,E)是一个无向连通带权图(无向连通网),E中每条 边(v,w)的权为c[v][w]. 如果G的一个子图G’是一棵包含G的所有顶点的树,则称G’为 G的生成树. 生成树上各条边权的总和称为该生成树的耗费,在G的所有 生成树中,耗费最小的生成树称为G的最小生成树.
第4章 贪心算法(1)活动安排问题
4.1 活动安排问题
活动安排问题是可以用贪心算法有效求解的很 好例子。
该问题要求高效地安排一系列争用某一公共资 源的活动,使得尽可能多的活动能兼容地使用 公共资源。
4
问题描述
设有n个活动的集合E={1, 2, …, n},其中每个 活动都要求使用同一资源,而在同一时间内只 有一个活动能使用这一资源。
2
贪心算法
例2:若上述硬币面值改为:
一角一分、五分和一分 现在要找给顾客一角五分钱,如何给出硬币? 答案:错:1个一角一分,4个一分
对:3个五分
虽然贪心算法不能对所有问题都得到整体最优 解,但对许多问题它能产生整体最优解。
在一些情况下,即使贪心算法不能得到整体最 优解,其最终结果却是最优解的很好的近似解。
ቤተ መጻሕፍቲ ባይዱ17
0-1背包问题
给定n种物品和一个背包。物品i的重量是wi, 其价值为vi,背包的容量为c。应如何选择装 入背包的物品,使得装入背包中物品的总价 值最大?
说明:在选择装入背包的物品时,对每种物 品i只有2种选择,即装入背包或不装入背包。 不能将物品i装入背包多次,也不能只装入部 分的物品i。
16
3、贪心算法与动态规划算法的 差异
贪心算法和动态规划算法都要求问题具有最 优子结构性质,这是两类算法的一个共同点。
对于具有最优子结构的问题应该选用贪心算 法还是动态规划算法求解?
是否能用动态规划算法求解的问题也能用贪 心算法求解?
下面研究2个经典的组合优化问题,并以此 说明贪心算法与动态规划算法的主要差别。
每个活动i都有一个要求使用该资源的起始时 间si和一个结束时间fi,且si <fi 。
5
问题描述
如果选择了活动i,则它在半开时间区间[si, fi) 内占用资源。若区间[si, fi)与区间[sj, fj)不相交, 则称活动i与活动j是相容的。也就是说,当si≥fj
4-贪心法
应用实例
活动安排问题—算法设计与分析
template<class Type> void GreedySelector(int n, Type s[], Type f[], bool A[]) { A[1] = true; int j = 1; for (int i=2;i<=n;i++) { if (s[i]>=f[j]) { A[i]=true; j=i; } else A[i]=false; } }
贪心法的正确性问题
针对具体问题不同,贪心策略的选择可能有多种 ,如何选择合适的贪心策略并证明该策略的正确 性是贪心算法设计中的一个关键问题。 一般可以通过对算法步数的归纳或通过对问题规 模的归纳来证明贪心法的正确性。
应用实例
活动安排问题
有n个活动申请使用同一个礼堂,每项活动有一个开始时间和一 个截止时间,如果任何两个活动不能同时举行,问如何选择这 些活动,从而使得被安排的活动数量达到最多? 设S={1, 2, …, n}为活动的集合,si和fi分别为活动i的开始和截止 时间,i=1, 2, …, n。定义 活动i与j相容:si ≥ fj或sj ≥fi, i≠j 求S最大的两两相容的活动子集。 蛮力法 动态规划方法
若硬币的面值改为一角一分、五分和一分,要找给顾客的 是一角五分,情况如何?
贪心算法的基本思想
顾名思义,贪心算法总是作出在当前看来最好的 选择。也就是说贪心算法并不从整体最优考虑, 它所作出的选择只是在某种意义上的局部最优选 择。 贪心算法不能对所有问题都得到整体最优解,但 对许多问题它能产生整体最优解。 在一些情况下,即使贪心算法不能得到整体最优 解,其最终结果却是最优解的很好近似。
4—贪心法 Greedy Approach
第四章-贪心算法(模拟试题)
第四章-贪⼼算法(模拟试题)计算机与信息科学学院2010-2011学年第2学期模拟试卷计算机算法设计与分析—第四章.贪⼼算法本卷满分100分完卷时间120分钟⼀. 简答题(每⼩题2分,共20分)1. 当⼀个问题具有且具有时可⽤贪⼼算法,如最⼩⽣成树问题(背包问题,活动安排问题等)。
2. 在动态规划可⾏的基础上满⾜才能⽤贪⼼。
3. 贪⼼算法总是作出在当前看来最好的选择。
也就是说贪⼼算法并不从整体最优考虑,它所作出的选择只是在某种意义上的选择。
4. 动态规划算法通常以的⽅式解各⼦问题,⽽贪⼼算法则通常以的⽅式进⾏,以迭代的⽅式作出相继的贪⼼选择,每作⼀次贪⼼选择就将所求问题简化为规模更⼩的⼦问题5. 贪⼼算法和动态规划算法都要求问题具有性质,这是2类算法的⼀个共同点。
6. 当⼀个问题的最优解包含其⼦问题的最优解时,称此问题具有。
7. 对于具有n 个顶点和e 条边的带权有向图,如果⽤带权邻接矩阵表⽰这个图,那么Dijkstra 算法的主循环体需要时间。
这个循环需要执⾏n-1次,所以完成循环需要时间。
算法的其余部分所需要时间不超过。
8. 0-1背包问题指:给定n 种物品和⼀个背包。
物品i 的重量是Wi ,其价值为Vi ,背包的容量为C 。
应如何选择装⼊背包的物品,使得装⼊背包中物品的最⼤。
9. 有⼀批集装箱要装上⼀艘载重量为c 的轮船。
其中集装箱i 的重量为Wi 。
最优装载问题要求确定在不受限制的情况下,将装上轮船。
10. 多机调度问题要求给出⼀种作业调度⽅案,使所给的n 个作业在由m 台机器加⼯处理完成。
⼆. 综合题(1-6题每题7分,7-8题每题9分,共60分)1. 有4个物品,其重量分别为(4, 7, 5, 3),物品的价值分别为(40, 42, 25,12),背包容量为10。
试设计3种贪⼼策略,并给出在每种贪⼼策略下背包问题的解。
)(n O2. 使⽤prim算法构造出如下图G的⼀棵最⼩⽣成树。
dist(1,2)=6;dist(2,5)=3;dist(5,6)=6;dist(6,4)=2;dist(4,1)=5;dist(1,3)=1;dist(2,3)=5;dist(3,4)=5;dist(3,6)=4;dist(5,3)=63. 设有n项独⽴的作业{1,2,…, n},由m台相同的机器加⼯处理。
贪心算法题库
贪心算法是一种在每一步选择中都采取当前情况下的局部最优选择,并希望导致结果是全局最优解的算法。
下面是一些贪心算法的题目和解答:1. 旅行商问题(Travelling Salesman Problem):问题描述:给定一个城市列表和一个距离列表,要求找出一条路径,使得路径上的所有城市都经过,且总距离最短。
贪心算法解法:首先对城市按照距离进行排序,然后从最近的两个城市开始,每次都选择距离当前位置最近的两个城市,直到遍历完所有城市。
由于贪心算法每次选择的都是当前情况下的最优解,因此最终得到的路径总距离是最短的。
2. 背包问题(Knapsack Problem):问题描述:给定一组物品,每个物品都有自己的重量和价值,要求在不超过背包总重量的情况下,如何选择物品使得背包中物品的总价值最大。
贪心算法解法:按照物品的重量对物品进行排序,然后每次选择重量最小的物品,直到背包已满或无物品可选。
由于贪心算法每次选择的都是当前情况下的最优解,因此最终得到的方案总是可以找到一个大于等于当前最优解的方案。
3. 网格找零问题(Currency Change Problem):问题描述:给定一组面值不同的硬币,要求用最少的组合方式从一定金额中找零。
贪心算法解法:首先对硬币面值进行排序,然后每次使用当前面值最小的硬币进行组合,直到金额为零或无硬币可选。
贪心算法在此问题中的思路是每次选择最小的硬币进行使用,这样可以保证找零的最小数量。
以上题目和解答只是贪心算法的一部分应用,实际上贪心算法在许多其他领域也有广泛的应用,例如网页布局优化、任务调度、网络流等等。
贪心算法的优势在于其简单易懂、易于实现,但也有其局限性,例如无法处理一些存在冲突的情况或最优解不唯一的问题。
因此在实际应用中需要根据具体问题选择合适的算法。
江西科学技术版小学信息技术五年级下册《主题活动:贪心算法》同步练习题附知识点归纳
江西科学技术版小学信息技术五年级下册《主题活动:贪心算法》同步练习题附知识点归纳一、课文知识点归纳: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++贪心算法经典例题和详解贪心算法(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` 用于排序。
贪婪算法(例题及相关解答)
第 1 章贪婪算法虽然设计一个好的求解算法更像是一门艺术,而不像是技术,但仍然存在一些行之有效的能够用于解决许多问题的算法设计方法,你可以使用这些方法来设计算法,并观察这些算法是如何工作的。
一般情况下,为了获得较好的性能,必须对算法进行细致的调整。
但是在某些情况下,算法经过调整之后性能仍无法达到要求,这时就必须寻求另外的方法来求解该问题。
本章首先引入最优化的概念,然后介绍一种直观的问题求解方法:贪婪算法。
最后,应用该算法给出货箱装船问题、背包问题、拓扑排序问题、二分覆盖问题、最短路径问题、最小代价生成树等问题的求解方案。
1.1 最优化问题本章及后续章节中的许多例子都是最优化问题( optimization problem),每个最优化问题都包含一组限制条件( c o n s t r a i n t)和一个优化函数( optimization function),符合限制条件的问题求解方案称为可行解(feasible solution),使优化函数取得最佳值的可行解称为最优解(optimal solution)。
例1-1 [ 渴婴问题] 有一个非常渴的、聪明的小婴儿,她可能得到的东西包括一杯水、一桶牛奶、多罐不同种类的果汁、许多不同的装在瓶子或罐子中的苏打水,即婴儿可得到n 种不同的饮料。
根据以前关于这n 种饮料的不同体验,此婴儿知道这其中某些饮料更合自己的胃口,因此,婴儿采取如下方法为每一种饮料赋予一个满意度值:饮用1盎司第i 种饮料,对它作出相对评价,将一个数值s i 作为满意度赋予第i 种饮料。
通常,这个婴儿都会尽量饮用具有最大满意度值的饮料来最大限度地满足她解渴的需要,但是不幸的是:具有最大满意度值的饮料有时并没有足够的量来满足此婴儿解渴的需要。
设a i是第i 种饮料的总量(以盎司为单位),而此婴儿需要t 盎司的饮料来解渴,那么,需要饮用n种不同的饮料各多少量才能满足婴儿解渴的需求呢?设各种饮料的满意度已知。
贪心算法经典例题
贪心算法经典例题贪心算法是一种求解最优问题的算法思想,其核心理念是每一步都选择当前最优的策略,从而达到全局最优解。
贪心算法可以应用于许多经典问题,下面将介绍几个常见的贪心算法经典例题及相关参考内容。
1. 会议室安排问题题目描述:给定一组会议的开始时间和结束时间,求解如何安排会议,使得尽可能多的会议可以在同一时间段内进行。
解题思路:贪心算法可以通过每次选择结束时间最早的会议来求解。
首先将会议按照结束时间排序,选择第一个会议作为首先安排的会议,然后依次选择后续结束时间不冲突的会议进行安排。
相关参考内容:- 《算法导论》第16章:贪心算法(ISBN: 9787115265955)- 《数据结构与算法分析》第13章:贪心算法(ISBN: 9787302483626)2. 零钱兑换问题题目描述:给定一定面额的硬币,求解如何用最少的硬币数量兑换指定金额的零钱。
解题思路:贪心算法可以通过每次选择面额最大且不超过目标金额的硬币来求解。
从面额最大的硬币开始,尽可能多地选择当前面额的硬币,并减去已经选择的硬币金额,直到金额为0。
相关参考内容:- 《算法导论》第16章:贪心算法(ISBN: 9787115265955)- 《算法4》第1章:基础(ISBN: 9787302444627)3. 区间调度问题题目描述:给定一组区间,求解如何选择尽可能多的不重叠区间。
解题思路:贪心算法可以通过每次选择结束时间最早的区间来求解。
首先将区间按照结束时间排序,选择第一个区间作为首先选择的区间,然后依次选择后续结束时间不与已经选择的区间重叠的区间进行选择。
相关参考内容:- 《算法导论》第16章:贪心算法(ISBN: 9787115265955)- 《数据结构与算法分析》第13章:贪心算法(ISBN: 9787302483626)4. 分糖果问题题目描述:给定一组孩子和一组糖果,求解如何分配糖果,使得最多的孩子能够得到满足。
解题思路:贪心算法可以通过每次选择糖果最小且能满足当前孩子的糖果来求解。
贪心算法(4):作业排序问题
贪⼼算法(4):作业排序问题上⼀堂课程,我们学习了如何选择活动,使得在不发⽣冲突的前提下,能参与尽可能多的活动,这⾥没有考虑到不同的活动是否会带来不同的收益,假设它们的收益是⼀样的。
现在我们把问题修改下:有⼀系列作业,每个作业必须在各⾃的截⽌时间点之前完成,并且已知完成每个⼯作需要花费的时间以及带来的收益。
为了简单起见,假设完成每个⼯作都需要相等的单位时间,这样作业的截⾄时间点也就是单位时间的倍数。
再假设⼀次只能安排⼀个作业,完成⼀个作业后才能继续下⼀个作业。
问:如何选择作业并安排次序使它们能带来的总收益为最⼤?我们⽤例⼦A来说明。
【输⼊】有4个作业a,b,c,d。
它们各⾃的截⽌时间和能带来的收益如下:【输出】请找出⼀种能带来最⼤收益的作业执⾏次序。
在例⼦中,下列作业次序能带来最⼤的收益:{c, a}完成作业c,能带来的收益是40;因为做作业c,截⽌时间为1,它必须安排在0-1之间执⾏。
这样已经错过了b或d的截⽌时间点(1),因此⽆法再选择b或d,只能选择作业a,a的截⾄时间点为4,来得及完成。
做作业a的收益是20,因此完成作业c和a能带来的总收益是 40+20=60。
⽽选择其他次序的作业,都⽆法超过收益60。
参见下⾯的动图:我们再看⼀个例⼦B【输⼊】有5个作业a,b,c,d,e。
它们各⾃的截⽌时间和能带来的收益如下:请你选择和安排能获取最⼤收益的作业次序,先不给出答案,请你先思考,如何解答,然后再继续阅读。
算法分析⼀个简单粗暴的算法就是⽣成给定作业集合的所有⼦集,并检查每⼀个⼦集以确定该⼦集中作业的可⾏性,然后找出哪个可⾏⼦集可以产⽣最⼤收益。
这是⼀个典型的贪⼼算法。
算法思路如下:1)根据收益递减顺序对所有作业进⾏排序。
2)将结果序列初始化,并把已排序作业中的第⼀个作业加⼊3)依次按下⾯的规则处理剩余的n-1个作业如果把当前作业加⼊结果序列,不会错过它的截⽌时间,那么把它加⼊结果序列;否则忽略当前的作业。
贪心算法-例题讲解
贪⼼算法-例题讲解前⾔:此博客在写作过程中参考了⼤量资料和博客,不能⼀⼀列举,还请见谅。
概述贪⼼法:从问题的某⼀个初始状态出发,逐步构造最优解从⽽向⽬标前进,并期望通过这种⽅法产⽣出⼀个全局最优解的⽅法贪⼼是⼀种解题策略,也是⼀种解题思想,⽽不是算法贪⼼策略与其他算法的区别贪⼼与递推:贪⼼法推进每⼀步不依据某⼀固定的递推式,⽽是当前看似最佳的贪⼼决策,不断的将问题归纳为更加⼩的相似的⼦问题贪⼼与动态规划:贪⼼是“⿏⽬⼨光”;动态规划是“统揽全局”贪⼼法的优缺点优点:思维复杂度低、代码量⼩、运⾏效率⾼、空间复杂度低等缺点:很难找到⼀个简单可⾏并且保证正确的贪⼼思路贪⼼算法的应⽤贪⼼算法的常⽤范围有明显的贪⼼可证明贪⼼策略的贪⼼(最常见的)贪⼼数据结构:堆/Kruskal/Prim/Dijkstra博弈/游戏策略,这些策略⼤多是贪⼼求较优解或多次逼近求最优解⼏个简单的贪⼼例⼦最优装载问题:给n个物体,第i个物体重量为wi,选择尽量多的物体,使得总重量不超过C贪⼼策略:先拿轻的部分背包问题:有n个物体,第i个物体的重量为wi,价值为vi,在总重量不超过C的情况下让总价值尽量⾼。
每⼀个物体可以只取⾛⼀部分,价值和重量按⽐例计算贪⼼策略:先拿性价⽐⾼的乘船问题:有n个⼈,第i个⼈重量为wi。
每艘船的载重量均为C,最多乘两个⼈。
⽤最少的船装载所有⼈贪⼼策略:最轻的⼈和最重的⼈配对例题(基础)1.删数问题-【问题描述】键盘输⼊⼀个⾼精度的正整数n(n<=240位),去掉其中任意s个数字后剩下的数字按照原来的次序将组成⼀个新的正整数。
编程对给定的n和s,寻求⼀种⽅案,使得剩下组成的新数最⼩。
贪⼼策略为:每⼀步总是选择⼀个使剩下的数最⼩的数字删去,即按⾼位到低位的顺序搜索,若各位数字递增,则删除最后⼀个数字,否则删除第⼀个递减区间的⾸字符。
然后回到串⾸,按上述规则再删除下⼀个数字。
重复以上过程s次,剩下的数字串便是问题的解了。
贪心算法例题
贪心算法例题
贪心算法是一种在每一步选择中都采取当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法。
以下是一个贪心算法的例子:
问题描述:有100个人在一酒吧,一次酒局中大家都决定向其他每个人敬酒,但只有距离较近的人之间才能互敬。
酒局结束后,每人都记录下他们之间互敬了多少次。
现给出所有人的互敬次数,找出互敬次数最多的那个人。
贪心策略:从最多互敬次数的人开始,每次都选择能互敬次数最多的人,直到达到最大互敬次数为止。
具体实现:
1. 首先将所有人的互敬次数存入一个数组中。
2. 从数组中找到互敬次数最多的人,假设其互敬次数为max_times。
3. 从数组中删除所有互敬次数小于max_times的人,因为他们的互敬次数已经确定不会超过max_times。
4. 重复步骤2和3,直到数组为空。
这个贪心算法的例子中,每次选择都是基于当前情况下的最优选择,希望通过这种方式达到全局最优的结果。
贪心算法例题
贪心算法例题1木板制造问题描述现在需要制造N块木板,每块木板都有一个长度L和宽度W。
用来制造木板的机器在使用之前需要花1分钟时间进行调节,而且,如果在制造完一块木板L0×W0之后继续制造木板L1×W1,那么除非满足L0≤L1且W0≤W1,否则在制造L1×W1之前仍要花费1分钟进行调节。
现在给出欲制造的N块木板的尺寸,你的任务是确定至少需要花多长时间调节机器。
时间复杂度要求实现O(N2)时间复杂度的算法。
本题算法的最优时间复杂度为Θ(NlogN)。
2 雷达安装问题描述在笛卡尔坐标系上,我们认为海岸线是x轴,陆地在x轴下方,海洋在x轴上方,而每个岛屿都认为是海中的一个点。
现在要在海岸线上安装一些雷达,雷达的覆盖半径为d。
如果某个岛屿与离它最近的雷达之间的距离不超过d,这个岛屿就被监视了。
现在有N个岛屿需要监视,给出这N个岛屿的坐标,你的任务是确定为了监视所有的岛屿至少需要安装多少个雷达。
时间复杂度要求实现Θ(NlogN)时间复杂度的算法,而这也是本题时间复杂度的下限。
3 修理牛棚问题描述农夫约翰的牛棚是N个房间一个紧挨着一个排成一行的结构,每个房间的宽度都是1。
在一个暴风雨的夜晚,牛棚所有的天花板都被吹走了。
好在许多牛正在度假,所以牛棚没有住满,有些房间里面有牛,有些没有。
一共有S (1≤S≤N)个房间是有牛居住的。
农夫约翰打算至少先把有牛居住的房间的屋顶修好。
他的木材提供商只愿意提供M块木板,但是每块木板都可以是任意长度的。
农夫约翰想知道他至少需要购买多长的木板才能把牛都盖住。
时间复杂度要求实现O(NlogN)复杂度的算法。
本题算法的最优时间复杂度为Θ(N)。
贪心算法
西安邮电大学计算机学院
第4章 贪心算法
4.2.1 贪心选择性质
(1)贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择, 即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态 规划算法的主要区别。
西安邮电大学计算机学院
第4章 贪心算法
西安邮电大学计算机学院
第4章 贪心算法
4.3.2 贪心选择性质
西安邮电大学计算机学院
第4章 贪心算法
4.3.3 最Βιβλιοθήκη 子结构性质由最优装载问题的贪心选择性质和最优子结构性质,容易证明算法 Loading 的
正确性。算法 Loading 的主要计算量在于将集装箱依其重量从小到大排序,故
第4章 贪心算法
4.3 最优装载
本节要求掌握解决最优装载问题的贪心算法以及此算法的贪心选择算法和最优 子结构性质的证明,是本课程的重点。 问题的提出:
西安邮电大学计算机学院
第4章 贪心算法
4.3.1 算法描述
最优装载问题可用贪心算法求解。采用重量最轻者先装的贪心选择策略,可产生 最优装载问题的最优解。具体算法描述如下:
第4章 贪心算法
贪心算法总是作出在当前看来最好的选择。也就是说贪心算 法并不从整体最优上加以考虑,它所作出的选择只是在某种
意义上的局部最优选择。当然,希望贪心算法得到的最终结
果也是整体最优的。虽然贪心算法不能对所有问题都得到整 体最优解,但对许多问题它能产生整体最优解。在一些情况 下,即使贪心算法不能得到整体最优解,其最终结果却是最 优解的很好近似。
集合,则 Aj = A - {j} 是 n – 1 个物品 1,2,…,j-1,j+1,…,n 可装入容量为 c
贪心习题
NYOJ-47 过河问题
在漆黑的夜里,N位旅行者来到了一座狭窄 而且没有护栏的桥边。如果不借助手电筒 的话,大家是无论如何也不敢过桥去的。 不幸的是,N个人一共只带了一只手电筒, 而桥窄得只够让两个人同时过。如果各自 单独过桥的话,N人所需要的时间已知;而 如果两人同时过桥,所需要的时间就是走 得比较慢的那个人单独行动时所需的时间。 问题是,如何设计一个方案,让这N人尽快 过桥。
2015/8/25 12
贪心策略
怎样选择最佳操作?
优先选择小的木板
可以肯定的是:每次首先选l, w尽可能小 的wooden stick 。
2015/8/25
13
具体处理:
(1)先以l为第一关键字w为第二关键字对 这些木板进行排序, (2)从未完成的木板中选择第一块完成 (选择的理由:最短(最轻)的木板) (3)然后看哪些木板能在选择木板的基础 上不需要额外时间,先完成; (4)重复(2)(3)过程,一直到木板全 加工完。
NYOJ-6 喷水装置
现有一块草坪,长为20米,宽为2米,要在 横中心线上放置半径为Ri的喷水装置,每个 喷水装置的效果都会让以它为中心的半径 为实数Ri(0<Ri<15)的圆被湿润,这有充足 的喷水装置i(1<i<600)个,并且一定能把 草坪全部湿润,你要做的是:选择尽量少 的喷水装置,把整个草坪的全部湿润。
King: 200 180 160 Tianji: 190 170 150
2015/8/25
17
Case 2:
King: 200 180 160 Tianji: 210 170 150
2015/8/25
18
Case 3:
King: 200 180 160 Tianji: 180 155 150
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第四章作业 部分参考答案1. 设有n 个顾客同时等待一项服务。
顾客i 需要的服务时间为n i t i ≤≤1,。
应该如何安排n 个顾客的服务次序才能使总的等待时间达到最小?总的等待时间是各顾客等待服务的时间的总和。
试给出你的做法的理由(证明)。
策略:对 1i t i n ≤≤进行排序,,21n i i i t t t ≤≤≤ 然后按照递增顺序依次服务12,,...,ni i i 即可。
解析:设得到服务的顾客的顺序为12,,...,n j j j ,则总等待时间为,2)2()1(1221--+++-+-=n n j j j j t t t n t n T 则在总等待时间T 中1j t 的权重最大,jnt 的权重最小。
故让所需时间少的顾客先得到服务可以减少总等待时间。
证明:设,21n i i i t t t ≤≤≤ ,下证明当按照不减顺序依次服务时,为最优策略。
记按照n i i i 21次序服务时,等待时间为T ,下证明任意互换两者的次序,T都不减。
即假设互换j i ,)(j i <两位顾客的次序,互换后等待总时间为T ~,则有.~T T ≥由于,2)2()1(1221--+++-+-=n n i i i i t t t n t n T,2)()()2()1(1221--+++-++-++-+-=n n j i i i i i i i t t t j n t i n t n t n T ,2)()()2()1(~1221--+++-++-++-+-=n n i j i i i i i i t t t j n t i n t n t n T则有.0))((~≥--=-i j i i t t i j T T同理可证其它次序,都可以由n i i i 21经过有限次两两调换顺序后得到,而每次交换,总时间不减,从而n i i i 21为最优策略。
2. 字符h a ~出现的频率分布恰好是前8个Fibonacci 数,它们的Huffman 编码是什么?将结果推广到n 个字符的频率分布恰好是前n 个Fibonacci 数的情形。
Fibonacci 数的定义为:1,1,11210>+===--n if F F F F F n n n解:前8个数为a , b , c , d , e , f , g , h1, 1, 2, 3, 5, 8, 13, 21Huffman 哈夫曼编码树为:所以a 的编码为:1111111 b 的编码为:1111110 c 的编码为:111110 d 的编码为:11110e 的编码为:1110f 的编码为:110g 的编码为:10 h 的编码为:0推广到n 个字符:第1个字符: n-1个1,1111-n 第2个字符: n-2个1,1个0, 01112-n 第3个字符: n-3个1,1个0, 01113-n ……第n-1个字符:1个1 ,1个0, 10 第 n 个字符:1个0 , 03. 设n p p p ,,,21 是准备存放到长为L 的磁带上的n 个程序,程序i p 需要的带长为i a 。
设L a ni i >∑=1,要求选取一个能放在带上的程序的最大子集合(即其中含有最多个数的程序)Q 。
构造Q 的一种贪心策略是按i a 的非降次序将程序计入集合。
1) 证明这一策略总能找到最大子集Q ,使得∑∈≤Qp ii L a 。
2) 设Q 是使用上述贪心算法得到的子集合,磁带的利用率可以小到何种程度? 3) 试说明1)中提到的设计策略不一定得到使∑∈Qp ii L a /取最大值的子集合。
1)证明:不妨设12...n a a a ≤≤≤,若该贪心策略构造的子集合Q 为},,,{21s a a a ,则s 满足∑∑=+=>+≤si s s si i L a a L a 111、。
要证明能找到最大子集,只需说明s 为可包含的最多程序段数即可。
即证不存在多于s 个的程序集合)(},,,,{~21s k a a a Q k i i i >= ,使得∑∈≤Qp i i L a ~。
反证法,假设存在多于s 个的程序集)(},,,,{~21s k a a a Q k i i i >= ,满足∑=≤kj i L a j 1。
因为12...n a a a ≤≤≤非降序排列,则L a a a a a a a k i i i k s ≤+++≤++++ 2121。
因为s k >且为整数,则其前s+1项满足L a a a a s s ≤++++121 。
这与贪心策略构造的子集和Q 中s 满足的∑=+>+si s sL a a11矛盾。
故假设不成立,得证。
2)磁带的利用率为∑∈Qp ii L a/;(甚至最小可为0,此时任意L a i >或者∑∈<<Qp i i L a )3)按照1)的策略可以使磁带上的程序数量最多,但程序的总长度不一定是最大的,假设},,,{21i a a a 为Q 的最大子集,但是若用1+i a 代替i a ,仍满足∑-=+<+111i k i kL a a,则},,,,{1121+-i i a a a a 为总长度更优子集。
4.答案见后面所附程序。
5. 已知n 种货币12,,,nc c c 和有关兑换率的n n ⨯表R ,其中[,]R i j 是一个单位的货币i c可以买到的货币j c 的单位数。
1)试设计一个算法,用以确定是否存在一货币序列12,,,ki i i c c c 使得:12231[,][,][,]1kR i i R i i R i i > 2)设计一个算法打印出满足1)中条件的所有序列,并分析算法的计算时间。
解:基本解题思想:通过FLOYD 算法求出最大环。
判断最大环的权值之积是否大于1,如果大于1说明可以实现套汇,如果不大于1 说明不能实现套汇。
在求解最大环的同时记录下兑换过程中的步骤。
算法实现的数据结构:int Path[MAX_VERTECX_NUM][MAX_VERTECX_NUM];//用来记录套汇过程中要经过的路径 float value[MAX_VERTECX_NUM][MAX_VERTECX_NUM];//用来记录经过讨回操作后得到的值 //借助图来实现该算法 typedef struct{int vexs[MAX_VERTECX_NUM]; //顶点向量 每种货币对应一个顶点float arc[MAX_VERTECX_NUM][MAX_VERTECX_NUM];//邻接矩阵 存放兑换率信息 int vexnum,arcnum; //图中当前顶点数和弧数 }MGraph; 算法中的关键步骤:for(k=1;k<=G->vexnum;k++) {for(i=1;i<=G->vexnum;i++) {for(j=1;j<=G->vexnum;j++) {if(value[i][k]*value[k][j]>value[i][j])//这里判断是否使兑换率增大,如果增大则记录下来 {value[i][j]=value[i][k]*value[k][j]; Path[i][j]=Path[k][j]; } } }}在输出兑换序列时采用了递归算法:这个算法逆序输出了兑换序列。
void Procedure_print(int i,int j){if(Path[i][j]==i){printf("%d",i);return;}else if(Path[i][j]==0)//输出结点i与结点j之间不存在通路printf("NO path");else{printf("%d ",Path[i][j]);Procedure_print(i,Path[i][j]);//{递归,货币I至J中间顶点}}}此算法的时间复杂度是:O(v^3)算法实现代码:#include<stdio.h>#define MAX_VERTECX_NUM 20#define INT_MIN 0int n;int Path[MAX_VERTECX_NUM][MAX_VERTECX_NUM];float value[MAX_VERTECX_NUM][MAX_VERTECX_NUM];typedef struct{int vexs[MAX_VERTECX_NUM]; //顶点向量可以存储每个顶点的信息float arc[MAX_VERTECX_NUM][MAX_VERTECX_NUM];//邻接矩阵主要存放关于边的信息int vexnum,arcnum; //图中当前顶点数和弧数}MGraph;void CreateDG(MGraph *G){int i,j,k;float w;scanf("%d%d",&(G->vexnum),&(G->arcnum));printf("G->vexnum=%d,G->arcnum=%d\n",G->vexnum,G->arcnum);for(i=1;i<=G->vexnum;i++){G->vexs[i]=i;}for(i=1;i<=G->vexnum;i++){for(j=1;j<=G->vexnum;j++){G->arc[i][j]=INT_MIN;}}for(k=1;k<=G->arcnum;k++){scanf("%d%d%f",&i,&j,&w);G->arc[i][j]=w;}}void ShortestPath_FLOYD(MGraph *G){int i,j,k;for(i=1;i<=G->vexnum;i++){for(j=1;j<=G->vexnum;j++){if(i==j)value[i][j]=1;elsevalue[i][j]=G->arc[i][j];if(G->arc[i][j]>INT_MIN)Path[i][j]=i;elsePath[i][j]=0;}}for(k=1;k<=G->vexnum;k++){for(i=1;i<=G->vexnum;i++){for(j=1;j<=G->vexnum;j++){if(value[i][k]*value[k][j]>value[i][j]){value[i][j]=value[i][k]*value[k][j];Path[i][j]=Path[k][j];}}}}}void Procedure_print(int i,int j){if(Path[i][j]==i){printf("%d",i);return;}else if(Path[i][j]==0)//输出结点i与结点j之间不存在通路printf("NO path");else{printf("%d ",Path[i][j]);Procedure_print(i,Path[i][j]);}}int main(){int i,j;MGraph G;freopen("data.in","r",stdin);freopen("data.out","w",stdout);CreateDG(&G);ShortestPath_FLOYD(&G);i=1;if(value[i][i]>1){printf("%f ",value[i][i]);if(Path[i][i]!=0)printf("%d%d ",i,i);printf("兑换顺序的逆序输出:%d ",i);Procedure_print(i,i);printf("\n");}}4.同学们的几种不同答案构造哈夫曼树思想,将所有的节点放到一个队列中,用一个节点替换两个频率最低的节点,新节点的频率就是这两个节点的频率之和。