赞
踩
从贪心算法的定义可以看出,贪心法并不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部
最优解,而由问题自身的特性决定了该题运用贪心算法可以得到最优解。
我们看看下面的例子
例
1
均分纸牌(
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
)
[
输
出
]
:输出至屏幕。格式为:所有堆均达到相等时的最少移动次数。
[
输入输出样例
]
:
4
9 8 17 6
屏慕显示:
3
算法分析:设
a[i]
为第
i
堆纸牌的张数(
0<=i<=n
),
v
为均分后每堆纸牌的张数,
s
为最小移到次数。
我们用贪心法,按照从左到右的顺序移动纸牌。如第
i
堆
(0
的纸牌数
a[i]
不等于平均值,则移动一
次
(
即
s
加
1)
,分两种情况移动:
(
1
)
若
a[i]>v
,则将
a[i]-v
张纸牌从第
I
堆移动到第
I+1
堆;
(
2
)
若
a[i]
,则将
v -a[i]
张纸牌从第
I+1
堆移动到第
I
堆;
为了设计的方便,我们把这两种情况统一看作是将
a[I]-v
张牌从第
I
堆移动到第
I+1
堆;移动后有:
a[I]:=v
;
a[I+1]:=a[I+1]+a[I]-v
;
在从第
i+1
堆中取出纸牌补充第
i
堆的过程中,可能会出现第
i+1
堆的纸牌数小于零
(a[i+1]+a[i]-v<0 )
的情况。
如
n=3
,三堆纸牌数为(
1
,
2
,
27
)这时
v=10
,为了使第一堆数为
10
,要从第二堆移
9
张纸牌到第一堆,
而第二堆只有
2
张纸牌可移,这是不是意味着刚才使用的贪心法是错误的呢?
我们继续按规则分析移牌过程,从第二堆移出
9
张到第一堆后,第一堆有
10
张纸牌,第二堆剩下
-7
张纸
牌,再从第三堆移动
17
张到第二堆,刚好三堆纸牌数都是
10
,最后结果是对的,从第二堆移出的牌都可
以从第三堆得到。我们在移动过程中,只是改变了移动的顺序,而移动的次数不变,因此此题使用贪心法
是可行的。
源程序:
var
i,n,s:integer;v:longint;
a:array[1..100]of longint;
f:text;fil:string;
begin
readln(fil);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。