浅谈贪心算法

来源:互联网 发布:nginx视频教程 极客 编辑:程序博客网 时间:2024/06/16 00:47

收银员手里有足够多的100元、50元、20元、10元、5元、2元、1元面值的钱,现在要找给顾客57元,问怎样找钱能使钱的张数最少?

 

那么如果我把钱设计成只有1元、3元、4元面值的,那么可以用贪心吗?

比如要找给顾客6元,如果用贪心。应该先找1个4元的,然后是2个1元的,显然不是最优解。

 

贪心策略:不从整体最优考虑,而总是做出在某种意义上的局部最优。(总是做出当前来看是最好的选择,或者简单地说每次选择最好的

 

目的:最终结果也是整体最优的

 

特别说明:因其具有不能对所有问题都得到整体最优解的局限,因此必须首先证明使用贪心的整体结果是最优解

 

两个要素

问题的整体最优解总是可以通过一系列局部最优的选择来达到

 

1. 第一步局部选择:选择当前局部最优,保证该局部最优包含在整体最优的一系列策略中。

2. 下一步继续选择:整体最优的下一步还可以通过局部最优达到。

 

实现框架

从某一初始解开始;

while (逼近目标) {

         求出可行解的一个元素;

}

由所有解元素组合成问题的解;

 

举例一:活动选择

一个会议室在一天内有多场活动,每个活动有其开始时间StartTime和结束时间EndTime,如果选择这场活动,那么它就占据了[StartTime, EndTime)时间区间。请问如何选择活动使得在一天里安排的活动最多?

ID

1

2

3

4

5

6

7

8

9

10

11

StartTime[ID]

1

3

0

4

3

5

6

8

8

2

12

EndTime[ID]

4

6

6

7

8

9

10

11

12

13

14

表格中的结束时间已经按非递减排序。

 

想要安排的活动最多,可能会有这样几种思想:

1.      选择开始时间最早的活动;

2.      选择持续时间最短的活动;

3.      选择结束时间最早的活动。

 

下面给出第1、2种思想的反例:


结论:结束得早,就可以安排更多的活动!

 

举例二:背包问题

有一个背包,容量是80,如何使背包里的装的东西总价值最大,但是总重量不超过背包容量?

物品

A

B

C

D

重量

30

50

10

20

价值

40

50

40

15

 

那么可能会有下面的想法:

1.      每次挑价值最大的;

2.      每次挑重量最轻的;

3.      每次挑单位重量价值最大的。

 

这些想法对吗?

其实都不对。原因如下:

如果每次挑价值最大的,那么他的重量也可能大。就不能装更多的东西了。

举例:比如背包容量是50,挑选了价值最大的B,那么就不能再取了,但是取C和D更优!

如果每次挑重量最轻的,那么他的价值可能非常小,而重量大的价值可能非常大。同样也不合理。

如果选单位重量价值大的总该对了吧!也不对。如果存在商品的单位重量价值相等,但是受背包容量的限制,也可能不是最优解。

比如:

物品

A

B

C

重量

45

10

40

价值

45

10

40

那么显然选A就不合适了,因此在单位重量价值相等的条件下,还应先选取重量最小的。

 

举例三:拼数(NOIP 1998提高组)

题目描述Description

设有n个正整数(n≤20),将它们联接成一排,组成一个最大的多位整数。

例如:n=3时,3个整数13,312,343联接成的最大整数为:34331213

又如:n=4时,4个整数7,13,4,246联接成的最大整数为:7424613

 

输入输出格式Input/output

输入格式:

第一行,一个正整数n。

第二行,n个正整数。

输出格式:

一个正整数,表示最大的整数

 

输入输出样例 Sampleinput/output

样例测试点#1

输入样例:

3

13

131

343

输出样例:

34313131

 

说明description

30%的数据, n≤10,每个数<10^3。 50%的数据, n≤100。 100%的数据, n≤1000,每个数<10^200。

 

分析:如果比较两个整数的大小,把大的数放在前面,小的数放在后面,看起来没有任何问题。但是假如是12和121,那么12112显然就不是最大的数了,而是12121。那么不能用贪心了嘛?非也。因此我们不应该比较两个数的大小,而是比较两个字符串拼接的大小。如果a+b>=b+a,那么就把a排在b之前。实现如下:

import java.util.ArrayList;import java.util.Scanner;public class Main {public static void main(String[] args){String str = "";ArrayList<String> array = new ArrayList<String>();Scanner in = new Scanner(System.in);int n = in.nextInt();while(n-- > 0){array.add(in.next());}for(int i = 0; i < array.size(); i++){for(int j = i+1; j < array.size(); j++){if((array.get(i)+array.get(j)).compareTo(array.get(j)+array.get(i)) < 0){String tmp = array.get(i);array.set(i, array.get(j));array.set(j, tmp);}}}for(int i = 0; i < array.size(); i++){str += array.get(i);}System.out.println(str);}}

原创粉丝点击