洛谷 P1094 纪念品分组【贪心/双指针】

题目描述

元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得 的纪念品价值相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品, 并且每组纪念品的价格之和不能超过一个给定的整数。为了保证在尽量短的时间内发完所有纪念品,乐乐希望分组的数目最少。

你的任务是写一个程序,找出所有分组方案中分组数最少的一种,输出最少的分组数目。

输入输出格式

输入格式:

输入文件group.in包含n+2行:

第1行包括一个整数w,为每组纪念品价格之和的上上限。

第2行为一个整数n,表示购来的纪念品的总件数G

第3~n+2行每行包含一个正整数Pi (5 <= Pi <= w)表示所对应纪念品的价格。

输出格式:

输出文件group.out仅一行,包含一个整数,即最少的分组数目。

输入输出样例

输入样例#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

【分析】:先升序排序,尽量将最大最小的两个捆绑在一起,设置一前一尾双指针进行移动,直到i>j

【代码】:

#include <bits/stdc++.h>

using namespace std;

const int N = 30000+100;
int lim,n,a[N],cnt;
int main()
{
    ios::sync_with_stdio(false);
    cin>>lim;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    sort(a+1,a+n+1);
    cnt=0;
    int i=1,j=n;
    while(i<=j)
    {
        if(a[i]+a[j]>lim)
        {
            cnt++;
            j--;
        }
        else
        {
            cnt++;
            i++;
            j--;
        }
    }
    cout<<cnt<<endl;
    return 0;
}
//20 20 30 50 60 70 80 90 90   //cnt 0+1+1+1+1+1
 //        i     j

时间: 2024-10-02 14:39:12

洛谷 P1094 纪念品分组【贪心/双指针】的相关文章

洛谷P1969 积木大赛 贪心 差分

洛谷P1969 积木大赛 贪心 考虑差分 对区间 [l,r]+1 在差分数组上相当于 d[ l ]++ ; d[ r+1 ]-- ; 那么你得到原数组的差分数组后 当d[ i ] = x 则你需要 对 以 i 为左端点 右端点未知的一个区间加x次且这x加的可能不是同一个区间 所以最后只要将差分数组中所有正数加上去就行了 同样其实也可以用负数算的,但是负数算的话,要加上 d[ n+1 ] 即 a[ n+1 ] - a[ n ] 或者另一种思路对于一段上升(不下降)区间,我们在搭最高层时可以把下面一

Luogu P1094 纪念品分组

Description 详见https://www.luogu.org/problem/show?pid=1094 Solution > -------这是一道不错的贪心,虽然代码很短,但是证明还是挺考思维的> -------先从大到小排序> ------- 刚开始想将最大的和他能搭配的最大的搭配,比如图中a可以和c和d,但是我想选择c, > -------但是仔细一想其实没这个必要,因为 ,如果a>b,c>d  而且 a+c<=w 那么b+c<=w  也就

洛谷——P1109 学生分组

P1109 学生分组 题目描述 有N组学生,给出初始时每组中的学生个数,再给出每组学生人数的上界R和下界L(L<=R),每次你可以在某组中选出一个学生把他安排到另外一组中,问最少要多少次才可以使N组学生的人数都在[L,R]中. 输入输出格式 输入格式: 第一行一个整数N,表示学生组数: n<=50 第二行N个整数,表示每组的学生个数: 第三行两个整数 L,R,表示下界和上界 输出格式: 一个数,表示最少的交换次数,如果不能满足题目条件输出-1 输入输出样例 输入样例#1: 复制 2 10 20

洛谷P2127 序列排序 [贪心]

题目传送门 题目描述 小C有一个N个数的整数序列,这个序列的中的数两两不同.小C每次可以交换序列中的任意两个数,代价为这两个数之和.小C希望将整个序列升序排序,问小C需要的最小代价是多少? 输入输出格式 输入格式: 第一行,一个整数N. 第二行,N个整数,表示小C的序列. 输出格式: 一行,一个整数,表示小C需要的最小代价. 输入输出样例 输入样例#1: 复制 6 8 4 5 3 2 7 输出样例#1: 复制 34 说明 数据范围: 对于30%的数据,1<=N<=10: 对于全部的数据,1&l

【洛谷】【堆+贪心】P1484 种树

[题目描述:] cyrcyr今天在种树,他在一条直线上挖了n个坑.这n个坑都可以种树,但为了保证每一棵树都有充足的养料,cyrcyr不会在相邻的两个坑中种树.而且由于cyrcyr的树种不够,他至多会种k棵树.假设cyrcyr有某种神能力,能预知自己在某个坑种树的获利会是多少(可能为负),请你帮助他计算出他的最大获利. [输入格式:] 第一行,两个正整数n,k. 第二行,n个正整数,第i个数表示在直线上从左往右数第i个坑种树的获利. [输出格式:] 输出1个数,表示cyrcyr种树的最大获利. 输

洛谷P1250种树(贪心)

题目描述 一条街的一边有几座房子.因为环保原因居民想要在路边种些树.路边的地区被分割成块,并被编号成1..N.每个部分为一个单位尺寸大小并最多可种一棵树.每个居民想在门前种些树并指定了三个号码B,E,T.这三个数表示该居民想在B和E之间最少种T棵树.当然,B≤E,居民必须记住在指定区不能种多于区域地块数的树,所以T≤E-B+l.居民们想种树的各自区域可以交叉.你的任务是求出能满足所有要求的最少的树的数量. 写一个程序完成以下工作: 输入输出格式 输入格式: 第一行包含数据N,区域的个数(0<N≤

acm未解之谜-洛谷P1109学生分组

把每一组的学生个数调度到一个给定区间范围内: 看了一圈题解,大佬都对原因避而不答: #include <iostream> #include <algorithm> using namespace std; const int maxn = 55; int sum=0,a[maxn],n,l,r; int main(){ cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; sum+=a[i]; } cin>>

[洛谷201704R1]开心派对小火车

OJ题号:洛谷P3697 思路: 贪心.首先从起点出发,开特急电车,对于每一个特急车站$s_{i}$,分别下一次车,计算从当前车站$s_{i}$出发坐各停电车在指定时限内$t$最远能够到达的车站$r_{i}$,并保证这个$r_{i}$不会超过$s_{i+1}$.将得到的站点$r_{i}$放入一个大根堆中,堆中的每个元素记录两个值,第一个用来保存如果在当前站点开通快速电车,从当前站点坐快速电车总共能到达的站的个数:第二个用来保存当前站的编号$r_i$.最后不断地从堆中挑选最优的站,重复拓展到新的站

洛谷P1080 国王游戏 高精度 贪心 数学推公式

洛谷P1080 国王游戏        数学推公式      高精度    贪心 然而这并不是我打出来的,抄题解... 将左手与右手的乘积从小到大排序,然后计算求最大值即可.(需要高精度) 证明: 1)知道,如果相邻的两个人交换位置,只会影响到这两个人的值,不会影响他人 2)假设相邻的两个人i, i + 1.设A[i] B[i] <= A[i + 1] B[i + 1],i之前所有人的左手乘积为S. 则,ans1 = max{S / B[i], S * A[i] / B[i + 1]} 若交换