问题描述
元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得 的纪念品价值相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品, 并且每组纪念品的价格之和不能超过一个给定的整数。为了保证在尽量短的时间内发完所有纪念品,乐乐希望分组的数目最少。
你的任务是写一个程序,找出所有分组方案中分组数最少的一种,输出最少的分组数目。
输入
第1行包括一个整数w,为每组纪念品价格之和的上上限。
第2行为一个整数n,表示购来的纪念品的总件数G
第3~n+2行每行包含一个正整数Pi (5 <= Pi <= w)w表示所对应纪念品的价格。
输出
包含一个整数,即最少的分组数目。
样例输入
100
9
90
20
20
30
50
60
70
80
90
样例输出
6
算法讨论
先从大到小排序,拿最大的加最小的,标记,不行就拿第二大的,以此类推,最后把没标记的加上。有个小优化,若不管怎样都无法再组合了,那就不用再找了,直接退出。
const
maxn=30000;
var
a:array[1..maxn] of longint;
f:array[1..maxn] of boolean;
i,j,n,s,w:longint;
flag:boolean;
procedure qsort(l,r:longint);
var
i,j,m,t:longint;
begin
i:=l; j:=r;
m:=a[(l+r) div 2];
repeat
while a[i]>m do
inc(i);
while a[j]<m do
dec(j);
if i<=j
then begin
t:=a[i]; a[i]:=a[j]; a[j]:=t;
inc(i); dec(j)
end;
until i>j;
if l<j
then qsort(l,j);
if i<r
then qsort(i,r)
end;
begin
read(w);
read(n);
for i:=1 to n do
read(a[i]);
qsort(1,n);
for i:=n downto 1 do
begin
flag:=false;
for j:=1 to i-1 do
if (f[j]=false) and (a[i]+a[j]<=w) and (i<>j)
then begin
f[j]:=true;
f[i]:=true;
flag:=true;
inc(s);
break
end;
if flag=false
then break
end;
for i:=1 to n do
if f[i]=false
then inc(s);
write(s)
end.
Pixiv ID:61481273