【NOIP 2007】纪念品分组
题目描述
元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得 的纪念品价值相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品, 并且每组纪念品的价格之和不能超过一个给定的整数。为了保证在尽量短的时间内发完所有纪念品,乐乐希望分组的数目最少。
你的任务是写一个程序,找出所有分组方案中分组数最少的一种,输出最少的分组数目。
输入格式
共n+2行:
第1行包括一个整数w,为每组纪念品价格之和的上上限。
第2行为一个整数n,表示购来的纪念品的总件数G。
第3至n+2行每行包含一个正整数P i (5≤P i ≤w)表示所对应纪念品的价格。
输出格式
一个整数,即最少的分组数目。
输入输出样例
输入 #1 复制
100
9
90
20
20
30
50
60
70
80
90
输出 #1 复制
6
说明/提示
50%的数据满足:1≤n≤15
100%的数据满足:1≤n≤30000,80≤w≤200
分析
(学生会总喜欢搞这些有的没有,真的烦。。。。。。。哈哈说着玩,没进过也不知道。)
题目要求
(把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品, 并且每组纪念品的价格之和不能超过一个给定的整数。)
首先读入,从小到大排序。
我是这样想到,设一个k1=1,k2=n 然后从两头开始 枚举。最后k1==k2 代表枚举结束;
1每次让 k1 + k2 ; 如果 k1 + k2 > 给定的整数w 。那么表示不能合成一个组,那么让k2(大的那个) 单独一组。ans++,k2–;继续
2如果 k1 + k2 <= 给定的整数w,那么表示能合成一个组,k1++,k–; 继续
必须注意,每次k2-- 时,要判断 k2-- 后的k2 与k1是不是 同个数,是代表相撞了,枚举结束;
(文字假装是图片 : -> 数 数 数 k1 k2数数数 <-
,这时 k1 k2已经是相邻了。k2-- 已经没有能再减了。)
还要注意,如果k2–后与k1不是同个数, 让k1++, 这时也要判断 k2 是不是等于k1,是的话 表示他们都指向最后一个数,这个数 只能自己一组了。
(文字假装是图片 : -> 数 数 数 k1数 k2数数数 <-
,k2–后,k2来到中间那个数,这时 k1++。那么k1,k2就指向了同一个数, 那么这个数就单独一组啦,同时结束枚举)
代码
#include<iostream>
using namespace std;
#include<algorithm>
int w,n;
int a[30005];
bool cmp(int x,int y){
return x > y;
}
int main(){
cin>>w>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+1+n);
int k1=1,k2=n;
int ans=0;
while(k1!=k2){
//大的那个单独一组
if(a[k1] + a[k2] >w){
ans++;
k2--;
}else{ //两个合成一组
ans++;
k2--;
if(k1 == k2)break;
else k1++;
//剩单个
if(k1 == k2) {
ans++;
break;
}
}
}
return 0;
}