8贪心策略

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

{读入数据}
I := 1; repeat if M = 0 then Break; {如果卡车满载则跳出循环} M := M - Wi; if M >= 0 then 将第I种商品全部装入卡车 else 将(M + Wi)重量的物品I装入卡车; I := I + 1; {选择下一种商品} until (M <= 0) OR (I >= N)
● ● ● ● ● ● ● ● ● ● ● ●
输入: 4 9 8 17 6
输出: 3
设list为纸牌序列,其中list[i]为第i堆纸牌的张数(1≤i≤n), ave为均分后每堆纸牌的张数,即 ;ans为最少移动次 数。
n
list [ i ] n
i 1
我们采用“移动一次使得一堆牌数达到平均值”的贪心策略: 由左而右的顺序移动纸牌。若第i堆纸牌的张数list[i]超出平均 值,则移动一次(ans+1),将超出部分留给下一堆,既第i+1堆 纸牌的张数增加list[i]-ave;若第i堆纸牌的张数list[i]少于平均值, 则移动一次(ans+1),由下一堆补充不足部分,既第i+1堆纸牌 的张数减少ave-list[i];
试题中正整数N 的有效位数为240位,必须采用可含256个字 符的字串来替代整数。 贪心选择:使用尽可能逼尽目标的方法来逐一删去其中S个数 符,每一步总是选择一个使剩下的数最小的数符删去。具体: 按高位→低位的方向搜索递减区间。若不存在递减区间, 则删尾数符;否则删递减区间的首字符,这样形成了一个新 数串。然后回到串首,重复上述规则,删下一数符……依此 类推,直至删除S个数符为止。 例如:N='178543',S=4,删数过程如下:
右邻堆取的牌
问题是,在从第i+1堆中取出纸牌补充第i堆的过程中,可能会 出现第i+1堆的纸牌数小于零(list[i+1]-(ave-list[i])<0 )的情况, 这时可以理解为一个“先出后进”的栈。由于纸牌的总数是n 的倍数,因此后面的堆会补充第i+1堆ave-list[i]-list[i+1]+ ave 张纸牌,使其达到均分的要求。
贪心策略
授课:陈嘉庆
贪婪技术(Greedy Technique)
● 教学内容
● ● ● ● ● 背包问题的贪婪策略(Knapsack Problem) Prim算法 Kruskal算法 Dijkstra算法 哈夫曼树(Huffman Trees)
● 要求
● 掌握贪婪技术的原理、效率分析方法,以及 在常见问题问题中的应用。
算法分析
● 此题很容易想到使用贪心法,在考试时有很多同学把整数 按从大到小的顺序连接起来,测试题目的例子也都符合, 但最后测试的结果却不全对。按这种贪心标准,我们很容 易找到反例:12,121 应该组成12121而非12112,那么是 不是相互包含的时候就从小到大呢?也不一定,如:12, 123 就是12312而非12112,这样情况就有很多种了。是不 是此题不能用贪心法呢? ● 其实此题是可以用贪心法来求解,只是刚才的贪心标准不 对,正确的贪心标准是:先把整数化成字符串,然后再比 较a+b和b+a,如果a+b>b+a,就把a排在b的前面,反之 则把a排在b的后面。
1≤i≤n
∑ pixi
约束条件 ∑ wi xi ≤W 1≤i≤n
0≤xi≤1, pi>0, wi>0, 1≤i≤n
5
背包问题(Knapsack Problem)
方案1:按物品价 值降序装包
方案2:按物品重量 升序装包
方案3:按物品价值与重 量比值的降序装包
6
例1 部分背包问题
● 给定一个最大载重量为M的卡车和N种食品, 有食盐,白糖,大米等。已知第i种食品的 最多拥有Wi公斤,其商品价值为Vi元/公斤, 编程确定一个装货方案,使得装入卡车中 的所有物品总价值最大。
分析:
● 因为每一个物品都可以分割成单位块,单 位块的利益越大显然总收益越大,所以它 局部最优满足全局最优,可以用贪心法解 答,方法如下:先将单位块收益按从大到 小进行排列,然后用循环从单位块收益最 大的取起,直到不能取为止便得到了最优 解。
算法
● ● ● ● ● ● ● ● ● ● ●
问题初始化; 按Vi从大到小将商品排序;
例2 排队打水问题
● 有N个人排队到R个水龙头去打水,他们装 满水桶的时间为T1,T2,…,Tn为整数且 各不相等,应如何安排他们的打水顺序才 能使他们花费的时间最少?
分析
● 由于排队时,越靠前面的计算的次数越多, 显然越小的排在越前面得出的结果越小 (可以用数学方法简单证明,这里就不再 赘述),所以这道题可以用贪心法解答, 基本步骤:
第二堆补充第一堆
第三堆补充第二堆
第四堆补充第三堆
在枚举分牌方案时,是否可以 利用上述计数方法呢?
均分纸牌(NOIP2002tg)
● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● var i,n,s:integer;v:longint; a:array[1..100]of longint; f:text;fil:string; begin readln(fil); assign(f,fil);reset(f); readln(f,n);v:=0; for i:=1 to n do begin read(f,a[i]); inc(v,a[i]); end; v:=v div n; {每堆牌的平均数} for i:=1 to n-1 do if a[i]<>v then {贪心选择} begin inc(s);{移牌步数计数} a[i+1]:=a[i+1]+a[i]-v;{使第i堆牌数为v} end;{then} writeln(s); end.
讨论问题2:删数问题
● 键盘输入一个高精度的正整数N,去掉其中 任意S个数字后剩下的数字按左右次序组成 一个新的正整数。对给定的N和S,寻找一 种删数规则使得剩下得数字组成的新数最 小。
删数问题
键盘输入一个高精度的正整数N, 去掉 其中任 意S个数字后剩下的数字按原左右次序将组成一 个新的正整数。编程对给定的N和S,寻找一种 方案使得剩下的数字组成的新数最小。 输出应包括所去掉的数字的位置和组成的新的 正整数。(N不超过240位) 输入数据均不需判错。
● ●

0,1背包问题
● 给定一个最大载重量为M的卡车和N种动物。 已知第i种动物的重量为Wi,其最大价值为 Vi,设定M,Wi,Vi均为整数,编程确定一 个装货方案,使得装入卡车中的所有动物 总价值最大。
算法?
● 按贪心法,有反例. ● 设N=3,卡车最大载重量是100,三种动物 A、B、C的重量分别是40,50,70,其对 应的总价值分别是80、100、150。
问题讨论
下列问题 是否可以用贪心法解决此题?
讨论问题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) [输 出]: 输出至屏幕。格式为: 所有堆均达到相等时的最少移动次数。
部分背包问题(Knapsack Problem)
● 问题描述
● 已知有n种物品和一个可容纳W重量的背包,每种物品I 的重量为wi,假定将物品I的某一部分xi放入背包就会得 到pixi的效益(0≤xi≤1, pi>0) ,采用怎样的装包方法才 会使装入背包物品的总效益为最大呢?
● 问题的形式描述
极大化
均分纸牌(NOIP2002tg)
● [问题描述] 有 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) [输 出]:输出至屏幕。格式为:所有堆均达到相等时的最少移动次数。 [输入输出样例] a.in: 4 9 8 17 6 屏慕显示:3
↓ N='1 7 8 5 4 3' ↓ '1 7 5 4 3' ↓ '1 5 4 3' ↓ '1 4 3' '1 3'
write(‘N=’); readln(N); {输入数串} write(‘S=’); readln(S); {输入应删的数字个数} while S>0 do begin {逐一删去S个数符} i:=1; while (i<length(N)) and (N[i]<=N[i+1]) do inc(i);{搜索 递减区间} delete(N,i,1); {删去该区间的首数符} dec(S); end; {while} while(length(N)>1)and(N[1]=‘0’)do delete(N,1,1);{删去 串头的无用零} writeln(N); {输出剩下的数码}
在N行M列的正整数矩阵中,要求从每行中选出1个数, 使得选出的总共N个数的和最大。 分析:要使总和最大,则每个数要尽可能大,自然应该 选每行中最大的那个数。因此,我们设计出如下算法:
● ● ● ● ● ● ●
读入N, M,矩阵数据;
Total := 0; for I := 1 to N do begin 选择第I行最大的数,记为K; Total := Total + K; end; 输出最大总和Total; {对N行进行选择}
2
贪心方法的基本思想
● 贪心是一种解题策略,也是一种解题思想 ● 使用贪心方法需要注意局部最优与全局最优的关 系,选择当前状态的局部最优并不一定能推导出 问题的全局最优 ● 利用贪心策略解题,需要解决两个问题: ● 该题是否适合于用贪心策略求解 ● 如何选择贪心标准,以得到问题的最优/较优 解
引例
贪婪技术(Greedy Te百度文库hnique)
某一问题的n个输入
A(1)
是A的一 个子集
A(2)
满足一定 的条件

A(n-1) A(n)
约束条件
B1(1) B1(2)

B1(m)

Bk(1) Bk(2)

Bk(m)
取极值
该问题的一种解(可 行解)
最优解
目标函数
10
贪心策略求解的问题具有的特点:
● ● 可通过局部的贪心选择来达到问题的全局最优解。 运用贪心策略解题,一般来说需要一步步的进行多次的 贪心选择。在经过一次贪心选择之后,原问题将变成一 个相似的,但规模更小的问题,而后的每一步都是当前 看似最佳的选择,且每一个选择都仅做一次。 原问题的最优解包含子问题的最优解,即问题具有最优 子结构的性质。 在背包问题中,第一次选择单位质量最大的货物,它是 第一个子问题的最优解,第二次选择剩下的货物中单位 重量价值最大的货物,同样是第二个子问题的最优解, 依次类推。 但并不是所有具有最优子结构的问题都可以用贪心策略 求解。因为贪心往往是盲目的,需要使用更理性的方 法——动态规划(例如“0-1背包问题”与“部分背包 问题”)
● 将输入的时间按从小到大排序; ● 将排序后的时间按顺序依次放入每个水龙头 的队列中; ● 统计,输出答案。
(NOIP1998tg)
● (NOIP1998tg)设有n个正整数,将他们连接成 一排,组成一个最大的多位整数。例如:n=3时,3 个整数13,312,343,连成的最大整数为:34331213 ● 又如:n=4时,4个整数7,13,4,246连接成的最大整数 为7424613 ● 输入:N ● N个数 ● 输出:连接成的多位数
相关文档
最新文档