纪念品分组
(group.pas/c/cpp)
【题目描述】
元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得的纪念品价值相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品,并且每组纪念品的价格之和不能超过一个给定的整数。为了保证在尽量短的时间内发完所有纪念品,乐乐希望分组的数目最少。
你的任务是写一个程序,找出所有分组方案中分组数最少的一种,输出最少的分组数目。
【输入】
输入文件group.in包含n+2行:
第1行包括一个整数w,为每组纪念品价格之和的上限。
第2行为一个整数n,表示购来的纪念品的总件数。
第3~n+2行每行包含一个正整数pi (5 <= pi <= w),表示所对应纪念品的价格。
【输出】
输出文件group.out仅一行,包含一个整数,即最少的分组数目。
【输入输出样例】
group.in | group.out |
100 9 90 20 20 30 50 60 70 80 90 | 6 |
【限制】
50%的数据满足:1 <= n <= 15
100%的数据满足:1 <= n <= 30000, 80 <= w <= 200
===========================================
这道题可以用贪心。
每次选一个最大的和最小的,
相加若<=限制,则:inc(l);dec(r); inc(ans);
若>限制,则:dec(r); inc(ans);
若最后i=j 则:inc(ans);
--------------------------------
虽说有反例,但是数据太弱,还是过了。
经验:在感到很恼火的时候,首先打出部分分代码...
===========================================
var
w,n:longint;
a:array[1..30000]of longint;
//f:array[1..30000]of boolean;
procedure init;
begin
assign(input,'p1067.in');
assign(output,'p1067.out');
reset(input); rewrite(output);
end;
procedure terminate;
begin
close(input); close(output);
halt;
end;
procedure qsort(s,t:longint);
var
i,j:longint;
x:longint;
tem:longint;
begin
x:=a[(s+t)shr 1];
i:=s; j:=t;
repeat
while (i<=j) and (a[j]>x) do dec(j);
while (i<=j) and (a[i]<x) do inc(i);
if i<=j then
begin
tem:=a[i];
a[i]:=a[j];
a[j]:=tem;
inc(i);
dec(j);
end;
until i>j;
if i<t then qsort(i,t);
if s<j then qsort(s,j);
end;
procedure main;
var
l,r,i:longint;
ans:longint;
begin
readln(w);
readln(n);
for i:=1 to n do
readln(a[i]);
qsort(1,n);
// fillchar(f,sizeof(f),true);
l:=1; r:=n; ans:=0;
while l<r do
begin
if a[l]+a[r]<=w then
begin
inc(l); dec(r); inc(ans);
end
else
begin
dec(r); inc(ans);
end;
end;
if l=r then inc(ans);
writeln(ans);
end;
begin
init;
main;
terminate;
end.