第6章 贪心算法

合集下载

第六章-贪心算法

第六章-贪心算法

//每堆牌的张数减去平均数
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】排队打水问题

贪心算法基本步骤

贪心算法基本步骤

贪心算法基本步骤贪心算法是一种非常常用的算法思想,广泛应用于算法设计中。

本文将介绍贪心算法的基本步骤、实现方式、应用场景以及优缺点。

一、基本步骤贪心算法的基本步骤可概括为:定义最优解的性质->利用贪心策略获得局部最优解->将局部最优解合并成一个整体最优解。

具体来说,一般包括以下几个步骤:1. 确定问题的最优解性质:要知道问题的最优解应该具有怎样的性质或特征,这些性质可以用于判断一个解是否符合规则或结果是否符合要求。

2. 构造候选解集:根据最优解的性质,不断构造可行的候选解集合,并通过一定的方法筛选出其中的解。

3. 选择最优解:从候选解集中选择一个最优解。

4. 验证最优解:通过验证最优解是否合法(满足约束条件)以及是否为问题的最优解,来验证贪心策略的正确性。

二、实现方式贪心算法的实现方式是比较灵活的,有些问题可以通过贪心策略来解决,有些则不行。

一般而言,如果问题的最优解具有贪心选择性质(即每一步的局部最优解能导致全局最优解),则采用贪心策略是可行的。

对于一些场景,我们可以通过规律来得到贪心策略。

例如:1. 集合覆盖问题:从未被覆盖的地方中选择一个覆盖点集最大的点,并删除所有覆盖的集合;2. 分数背包问题:选择性价比最高的物品,先吸纳尽量多的物品,再考虑其他物品。

三、应用场景1. 背包问题:针对背包问题和其变种,常见的贪心策略有分数背包(与完全和01背包有区别)和完全背包问题;2. 活动安排问题:在一些课程、项目或活动间选择,使得能够安排最多活动;3. 区间选择问题:在一些区间间选择相互不重叠的区间,使得能够选出最大的区间数;4. 集合覆盖问题:在一些集合中选择最少的集合,使得能够覆盖所有元素。

四、优缺点优点:1. 算法简单:贪心算法通常比较简单,易于理解和实现;2. 运算速度快:其时间复杂度一般较低,运算速度很快;3. 可以作为其他算法的优化:贪心策略可以应用于其他算法的优化中。

缺点:1. 不一定能够得到最优解:贪心策略仅考虑当前的局部最优解,对于全局最优解可能产生影响;2. 单一性:贪心算法的结果是唯一的,难以应对变化条件的需要,一旦局部最优解不满足当前的情况,算法就会失去原先的效果;3. 实现困难:对于有些问题,贪心算法并不是很好实现,涉及到更多的问题分析和模型的构造。

贪心算法知识点总结

贪心算法知识点总结

贪心算法知识点总结1. 基本原理贪心算法的基本原理是每一步都选择当前状态下的最优解,以期望最终得到全局最优解。

具体来说,贪心算法通常可以分为以下几个步骤:1)从问题的某个初始解出发2)采用一种迭代的方式,逐步将初始解进行优化3)每一步都是基于当前状态的最优选择来进行优化4)直到无法再进行优化,得到问题的最优解由于贪心算法每一步都要选择局部最优解,因此贪心算法通常具有高效性。

然而,贪心算法并不适用于所有问题,其结果不一定是全局最优解。

因此,在使用贪心算法时需要注意问题的特性和约束条件,以免得到错误的结果。

2. 适用情况贪心算法通常适用于满足以下条件的问题:1)问题的最优解满足“最优子结构”性质:即问题的最优解包含了其子问题的最优解2)问题的求解过程具有“贪心选择性”:即每一步都选择当前状态下的最优解,并不需要考虑未来的后果3)问题的约束条件可以通过局部最优选择满足全局最优解:即问题的解空间中存在一些局部最优解,可以通过一系列的局部最优解构建全局最优解在实际应用中,贪心算法通常用于求解最优化问题,如最小生成树、最短路径、任务调度等问题。

由于贪心算法的高效性,它通常能够在较短的时间内得到较为接近最优解的结果。

然而,贪心算法并不适用于所有问题,对于一些问题,贪心算法将得到错误的结果。

因此,在使用贪心算法时需要谨慎选择问题类型和约束条件,以避免错误的结果。

3. 贪心算法实例在下面的部分,我们将介绍一些常见的贪心算法实例,包括背包问题、活动安排问题、霍夫曼编码等。

3.1 背包问题背包问题是一个经典的优化问题,它包括0-1背包问题、分数背包问题等多种类型。

在0-1背包问题中,给定n种物品和一个容量为C的背包,每种物品i的重量为w[i],价值为v[i],求在不超过背包容量的情况下,如何选择物品放入背包,可以使得背包中的总价值最大。

对于0-1背包问题,贪心算法通常不能得到最优解。

然而,在分数背包问题中,贪心算法通常可以得到近似的最优解。

贪心算法的概念和适用条件

贪心算法的概念和适用条件

贪心算法的概念和适用条件什么是贪心算法?贪心算法(Greedy Algorithm)是一种以局部最优解为导向的算法思想,通过每一步选择当前状态下的最佳操作来达到整体最优解的目标。

贪心算法的核心思想是每次都做出当前看来最优的选择,以期望能够达到整体的最优解。

贪心算法通常用于一些问题中,即每一步的选择只依赖于当前状态,而不考虑将来可能出现的情况。

贪心算法的适用条件:1. 贪心选择性质:贪心算法每一步都选择一个当前的最优解,此处的“最优”指的是局部最优。

这种最优选择可以确保问题能够被拆解,并且进行下一步求解。

2. 最优子结构性质:当问题的整体最优解能够通过局部最优解得到时,可以采用贪心算法求解。

这种情况下,问题的最优解可以由子问题的最优解推导出来。

3. 无后效性:贪心算法选择某一步操作时,只考虑当前状态,不会改变以前的操作,并且不关心未来的操作。

这种无后效性使得贪心算法在实际应用中操作简单、效率高。

贪心算法的基本步骤:1. 确定问题的局部最优解:贪心算法的核心是每一步都选择在当前情况下的最优解。

因此,需要确定问题如何拆解以及如何进行局部最优选择。

2. 定义问题的子问题:根据问题的最优子结构性质,将问题拆解为较小规模的子问题。

子问题应该是原问题的一个更小、更简单的实例。

3. 定义贪心选择策略:根据问题的特性,确定当前步骤下的最优选择策略。

这个选择应该是局部最优的,可以在不考虑子问题和整体未来状态的情况下得出。

4. 重复执行步骤2和3,直至求解出全局最优解。

贪心算法的优缺点:贪心算法具有简单易懂、快速高效的特点,适用于许多实际问题。

它可以避免穷举所有可能性,节省了计算时间。

此外,贪心算法常常能够找到近似最优解,尽管不一定能够保证全局最优解。

在实际问题中,近似最优解也往往可以满足实际需求。

然而,贪心算法并非适用于所有问题。

由于贪心算法只考虑当前状态的最优选择,而不考虑未来的影响,因此可能会导致局部最优解与全局最优解不一致。

贪 心 算 法

贪 心 算 法

贪心算法及几个常用的例题贪心算法:一、基本概念:所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择。

也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。

贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择。

必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。

所以对所采用的贪心策略一定要仔细分析其是否满足无后效性。

二、贪心算法的基本思路:1.建立数学模型来描述问题。

2.把求解的问题分成若干个子问题。

3.对每一子问题求解,得到子问题的局部最优解。

4.把子问题的解局部最优解合成原来解问题的一个解。

三、贪心算法适用的问题贪心策略适用的前提是:局部最优策略能导致产生全局最优解。

实际上,贪心算法适用的情况很少。

一般,对一个问题分析是否适用于贪心算法,可以先选择该问题下的几个实际数据进行分析,就可做出判断。

四、贪心算法的实现框架从问题的某一初始解出发;while (能朝给定总目标前进一步)利用可行的决策,求出可行解的一个解元素;由所有解元素组合成问题的一个可行解;五、贪心策略的选择因为用贪心算法只能通过解局部最优解的策略来达到全局最优解,因此,一定要注意判断问题是否适合采用贪心算法策略,找到的解是否一定是问题的最优解。

几个经典的例子:一、定义什么是贪心算法呢?所谓贪心算法是指,在对问题求解时,总是做出在当前看来最好的选择。

也就是说,不从整体最优解出发来考虑,它所做出的仅是在某种意义上的局部最优解。

贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题都能产生整体最优解或整体最优解的近似解。

贪心算法的基本思路如下:1. .建立数学模型来描述问题。

2. 把求解的问题分成若干个子问题。

3. 对每个子问题求解,得到每个子问题的局部最优解。

4. 把每个子问题的局部最优解合成为原来问题的一个解。

第六章 贪心算法

第六章 贪心算法

【输入样例】 3 13 312 343 【输出样例】 34331213
6、纪念品分组 元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作。为 使得参加晚会的同学所获得的纪念品价值相对均衡,他要把购来的纪 念品根据价格进行分组,但每组最多只能包括两件纪念品,并且每组 纪念品的价格之和不能超过一个给定的整数。为了保证在尽量短的时 间内发完所有纪念品,乐乐希望分组的数目最少。 你的任务是写一个程序,找出所有分组方案中分组数最少的一种, 输出最少的分组数目。
【输入样例】 100 (w,为每组纪念品价格之和的上限) 9 (n为购来纪念品的总件数) 90 20 20 30 50 60 70 80 90
【输出样例】 6 【限制】50%数据(n<=15) 100%数据(n<=30000)
7、合并果子 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分 成了不同的堆,多多决定把所有的果子合成一堆。每一次合并,多多可以把两 堆果子合并到一起,消耗的体力等于两堆果子重量之和。可以看出,所有的果 子经过n-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等 于每次合并所消耗体力之和。 因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能节省 体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你 的任务是设计出合并的次序方案,使得多多消耗的体力最少,并输出这个最小 的体力消费值。 例如有3种果子,数目依次为1、2、9。可以先将1、2堆合并,新堆数目为3, 耗费体力为3。接着将新堆与原来的第三堆合并,又得到新的堆,数目为12,耗 费体力为12。所以多多总共耗费体力=3+12=15。可以证明15为最小体力耗费值。
例2、部分背包问题 给定一个最大容量为m的背包和n种食品, 有食盐、大米、白糖等。已知第i种食品最多有wi公斤,其价值 为vi元/公斤,编程确定一个装货方案,使得装入背包中的所有 食品的总价值最大。

算法导论-贪心算法

算法导论-贪心算法
动态规划是一种通过将问题分解为子问题并存储子问 题的解来避免重复计算的技术。
贪心算法可以看作是动态规划的一种特例,其中只保 留了与当前状态和当前选择相关的子问题的解,而不
是保留所有子问题的解。
贪心算法通常在每一步选择中只考虑当前状态下的局 部最优解,而不是考虑所有可能的选择和未来的状态。
贪心算法的经述 • 贪心算法的基本思想 • 贪心算法的经典问题 • 贪心算法的实现与优化 • 贪心算法的性能分析 • 总结与展望
贪心算法概述
01
定义与特点
定义
贪心算法是一种在每一步选择中都采取当前情况下最好或最优(即最有利)的 选择,从而希望导致结果是最好或最优的算法。
无法保证全局最优解
贪心算法可能只得到局部最优解,而非全局最 优解。
缺乏理论支持
贪心算法的理论基础尚不完备,难以对所有情况做出准确预测。
贪心算法与其他算法的比较
与动态规划算法比较
动态规划算法通过将问题分解为子问题来求解,适合处理具有重叠子问题和最优子结构的问题;而贪 心算法则是每一步都选择当前最优的选择,希望这样的局部最优选择能够导致全局最优解。
法的时间复杂度。
需要注意的是,贪心算法并不总是能够提供最优解,因此在实际应用中, 需要权衡时间复杂度和解的质量。
空间复杂度分析
贪心算法的空间复杂度主要取决于算法 的存储需求。在某些情况下,贪心算法 可能需要大量的存储空间来存储中间结
果或数据结构。
在分析贪心算法的空间复杂度时,需要 考虑算法所需的存储空间和存储结构的 复杂性。通过将每个存储需求的空间复 杂度相加,可以得出整个算法的空间复
与分治算法比较
分治算法是将问题分解为若干个子问题,然后递归地求解这些子问题,再将子问题的解合并起来得到 原问题的解;而贪心算法是在每一步都做出在当前状态下最好或最优(即最有利)的选择,希望这样 的局部最优选择能够导致全局最优解。

贪心算法Greedy

贪心算法Greedy
具体算法可描述如下页:
void Knapsack(int n,float M,float v[],float w[],float x[]) {
Sort(n,v,w); int i; for (i=1;i<=n;i++) x[i]=0; float c=M; for (i=1;i<=n;i++) {
例如,设7个独立作业{1,2,3,4,5,6,7}由3台机 器M1,M2和M3加工处理。各作业所需的处理时 间分别为{2,14,4,16,6,5,3}。按算法greedy产生 的作业调度如下图所示,所需的加工时间为17。
例2.背包问题
0-1背包问题:
给定n种物品和一个背包。物品i的重量是Wi,其价值为 Vi,背包的容量为C。应如何选择装入背包的物品,使得 装入背包中物品的总价值最大?
在选择装入背包的物品时,对每种物品i只有2种选择,即装入 背包或不装入背包。不能将物品i装入背包多次,也不能只装入部 分的物品i。
背包问题:
template<class Type> void Loading(int x[], Type w[], Type c, int n) {
int *t = new int [n+1]; Sort(w, t, n); for (int i = 1; i <= n; i++) x[i] = 0; for (int i = 1; i <= n && w[t[i]] <= c; i++) {x[t[i]] = 1; c -= w[t[i]];} }
动态规划算法通常以自底向上的方式解各子问题,而 贪心算法则通常以自顶向下的方式进行,以迭代的方式 作出相继的贪心选择,每作一次贪心选择就将所求问题 简化为规模更小的子问题。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

【例2】部分背包问题 给定一个最大载重量为M的卡车和N种食品,有食盐,白糖,大米等。已知 第i种食品的最多拥有Wi公斤,其商品价值为Vi元/公斤,编程确定一个装货方案, 使得装入卡车中的所有物品总价值最大。 【算法分析】
因为每一个物品都可以分割成单位块,单位块的利益越大显然总收益越大,所以它 局部最优满足全局最优,可以用贪心法解答,方法如下:先将单位块收益按从大到小进 行排列,然后用循环从单位块收益最大的取起,直到不能取为止便得到了最优解。 因此我们非常容易设计出如下算法:
第六章 贪心算法
ቤተ መጻሕፍቲ ባይዱ
若在求解一个问题时,能根据每次所得到的局部最优解,推导出全局最 优或最优目标。那么,我们可以根据这个策略,每次得到局部最优解答,逐 步而推导出问题,这种策略称为贪心法。下面我们看一些简单例题。
【例1】在N行M列的正整数矩阵中,要求从每行中选出1个数,使得选出的总共N个 数的和最大。 【算法分析】 要使总和最大,则每个数要尽可能大,自然应该选每行中最大的那个数。因此, 我们设计出如下算法: 读入N, M,矩阵数据; Total := 0; For I := 1 to N do begin //对N行进行选择 选择第I行最大的数,记为K; Total := Total + K; End; 输出最大总和Total; 从上例中我们可以看出,和递推法相仿,贪心法也是从问题的某一个初始解出发, 向给定的目标递推。但不同的是,推进的每一步不是依据某一固定的递推式,而是做 一个局部的最优选择,即贪心选择(在例中,这种贪心选择表现为选择一行中的最大 整数),这样,不断的将问题归纳为若干相似的子问题,最终产生出一个全局最优解。 特别注意的是,局部贪心的选择是否可以得出全局最优是能否采用贪心法的关键 所在。对于能否使用贪心策略,应从理论上予以证明。下面我们看看另一个问题。
下面来看看0-1背包问题。 给定一个最大载重量为M的卡车和N种动物。已知第i种动物的重量为Wi, 其最大价值为Vi,设定M,Wi,Vi均为整数,编程确定一个装货方案,使得 装入卡车中的所有动物总价值最大。 【分析】对于N种动物,要么被装,要么不装,也就是说在满足卡车载重的 条件下,如何选择动物,使得动物价值最大的问题。 即确定一组X1,X2,…,Xn, Xi∈{0,1} f(x)=max(∑Xi*Vi) 其中,∑(Xi*Wi)≦W 从直观上来看,我们可以按照上例一样选择那些价值大,而重量轻的动 物。也就是可以按价值质量比(Vi/Wi)的大小来进行选择。可以看出,每做 一次选择,都是从剩下的动物中选择那些Vi/Wi最大的,这种局部最优的选择 是否能满足全局最优呢?我们来看看一个简单的例子: 设N=3,卡车最大载重量是100,三种动物A、B、C的重量分别是40, 50,70,其对应的总价值分别是80、100、150。 情况A:按照上述思路,三种动物的Vi/Wi分别为2,2,2.14。显然,我们 首先选择动物C,得到价值150,然后任意选择A或B,由于卡车最大载重为 100,因此卡车不能装载其他动物。 情况B:不按上述约束条件,直接选择A和B。可以得到价值 80+100=180,卡车装载的重量为40+50=90。没有超过卡车的实际载重,因 此也是一种可行解,显然,这种解比上一种解要优化。
因此,利用贪心策略解题,需要解决两个问题: 首先,确定问题是否能用贪心策略求解;一般来说,适用于贪心策略 求解的问题具有以下特点: ①可通过局部的贪心选择来达到问题的全局最优解。运用贪心策略解 题,一般来说需要一步步的进行多次的贪心选择。在经过一次贪心选择之 后,原问题将变成一个相似的,但规模更小的问题,而后的每一步都是当 前看似最佳的选择,且每一个选择都仅做一次。 ②原问题的最优解包含子问题的最优解,即问题具有最优子结构的性 质。在背包问题中,第一次选择单位重量价值最大的货物,它是第一个子 问题的最优解,第二次选择剩下的货物中单位重量价值最大的货物,同样 是第二个子问题的最优解,依次类推。 ③其次,如何选择一个贪心标准?正确的贪心标准可以得到问题的最 优解,在确定采用贪心策略解决问题时,不能随意的判断贪心标准是否正 确,尤其不要被表面上看似正确的贪心标准所迷惑。在得出贪心标准之后 应给予严格的数学证明。
参考程序主要框架如下:
ave:=0;step:=0; for i:=1 to n do begin read(a[i]); inc(ave,a[i]); //读入各堆牌张数,求总张数ave end; ave:=ave div n; //求牌的平均张数ave for i:=1 to n do a[i]:=a[i]-ave; //每堆牌的张数减去平均数 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]); //将第i堆牌移到第i+1堆中去 a[i]:=0; //第i堆牌移走后变为0 inc(step); //移牌步数计数 inc(i); //对下一堆牌进行循环操作 while (a[i]=0) and (i<j) do inc(i); //过滤移牌过程中产生的0 end; writeln(step); 点评:基本题(较易) 本题有3点比较关键:一是善于将每堆牌数减去平均数, 简化了问题;二是要过滤掉0(不是所有的0,如-2,3,0,-1中的0是不能过滤的); 三是负数张牌也可以移动,这是辩证法(关键中的关键)。
例如:n=175438 s=4 删数的过程如下: n=175438 //删掉7 15438 //删掉5 1438 //删掉4 138 //删掉8 13 //解为13 这样,删数问题就与如何寻找递减区间首字符这样一个简单的问题对应起来。 不过还要注意一个细节性的问题,就是可能会出现字符串串首有若干0的情况, 甚至整个字符串都是0的情况。按以上贪心策略编制的程序框架如下 输入n,s; while s>0 do begin i:=1; //从串首开始找 while (i<length(n)) and (n[i]<=n[i+1]) do i:=i+1; delete (n,i,1); //删除字符串n的第i个字符 s:=s-1; end; while (length(n)>1)and (n[1]=‘0’) do delete(n,1,1); 输出n; //删去串首可能产生的无用零
【算法分析】 如果你想到把每堆牌的张数减去平均张数,题目就变成移动正数,加 到负数中,使大家都变成0,那就意味着成功了一半!拿例题来说,平均张 数为10,原张数9,8,17,6,变为-1,-2,7,-4,其中没有为0的数,我 们从左边出发:要使第1堆的牌数-1变为0,只须将-1张牌移到它的右边 (第2堆)-2中;结果是-1变为0,-2变为-3,各堆牌张数变为0,-3,7,-4; 同理:要使第2堆变为0,只需将-3移到它的右边(第3堆)中去,各堆牌张 数变为0,0,4,-4;要使第3堆变为0,只需将第3堆中的4移到它的右边 (第4堆)中去,结果为0,0,0,0,完成任务。每移动1次牌,步数加1。 也许你要问,负数张牌怎么移,不违反题意吗?其实从第i堆移动-m张牌到 第i+1堆,等价于从第i+1堆移动m张牌到第i堆,步数是一样的。 如果张数中本来就有为0的,怎么办呢?如0,-1,-5,6,还是从左算 起(从右算起也完全一样),第1堆是0,无需移牌,余下与上相同;再比 如-1,-2,3,10,-4,-6,从左算起,第1次移动的结果为0,-3,3,10, -4,-6;第2次移动的结果为0,0,0,10,-4,-6,现在第3堆已经变为0 了,可节省1步,余下继续。
问题出现在什么地方呢?我们看看图23
从图23中明显可以看出,情况A,卡车的空载率比情况B高。也就是说,上 面的分析,只考虑了货物的价值质量比,而没有考虑到卡车的运营效率,因此, 局部的最优化,不能导致全局的最优化。 因此,贪心不能简单进行,而需要全面的考虑,最后得到证明。
【例3】排队打水问题
有N个人排队到R个水龙头去打水,他们装满水桶的时间为T1,T2,…,Tn为整数且 各不相等,应如何安排他们的打水顺序才能使他们花费的时间最少? 【算法分析】 由于排队时,越靠前面的计算的次数越多,显然越小的排在越前面得出的结果越小 (可以用数学方法简单证明,这里就不再赘述),所以这道题可以用贪心法解答,基本步 骤: (1)将输入的时间按从小到大排序; (2)将排序后的时间按顺序依次放入每个水龙头的队列中; (3)统计,输出答案。 【样例输出】 【样例输入】 23 //总共花费时间 4 2 //4人打水,2个水龙头 2 6 4 5 //每个打水时间 参考程序主要框架如下: read(n,r); Fillchar(S,Sizeof(S),0); J:=0; Min:=0; For I:=1 To N Do //用贪心法求解 Begin Inc(J); If J=R+1 Then J:=1; S[J]:=S[J]+A[I]; Min:=Min+S[J]; End; Writeln(Min); //输出解答
【例4】均分纸牌(NOIP2002) 有 N 堆纸牌,编号分别为 1,2,…, N。每堆上有若干张,但纸牌总数必 为 N 的倍数。可以在任一堆上取若干张纸牌,然后移动。 移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上;在 编号为 N 的堆上取的纸牌,只能移到编号为 N-1 的堆上;其他堆上取的纸牌, 可以移到相邻左边或右边的堆上。 现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。 例如 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) 4 9 8 17 6 【样例输出】(Playcard.out) 3
相关文档
最新文档