蓝桥杯 ALGO-34算法训练 纪念品分组

时间:2022-12-02 16:58:54

时间限制:1.0s 内存限制:256.0MB
关键字:贪心 排序
问题描述
  元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得的纪念品价值 相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品,并且每组纪念品的价格之和不能超过一个给定的整数。为了保证在尽量短的时 间内发完所有纪念品,乐乐希望分组的数目最少。
  你的任务是写一个程序,找出所有分组方案中分组数最少的一种,输出最少的分组数目。
输入格式
  输入包含n+2行:
  第1行包括一个整数w,为每组纪念品价格之和的上限。
  第2行为一个整数n,表示购来的纪念品的总件数。
  第3~n+2行每行包含一个正整数pi (5 <= pi <= w),表示所对应纪念品的价格。
输出格式
  输出仅一行,包含一个整数,即最少的分组数目。
样例输入
100
9
90
20
20
30
50
60
70
80
90
样例输出
6
数据规模和约定
  50%的数据满足:1 <= n <= 15
  100%的数据满足:1 <= n <= 30000, 80 <= w <= 200
【分析】
由于题目要求每组纪念品价格之和的上限,并且每组最多只能包括两件纪念品,由此可以知道如果某件纪念品价格大于价格上限减去最小值,则需要独立一组,等于上限与最小值的差值的价格可以和最小值分在同一组,剩余的任意组合成两组即可满足条件。
【参考代码】
C++:

#include "iostream"
#include "string"
#include "stdio.h"
#include "ctype.h"
#include "algorithm"
#include "stack"
#include "list"
#include "math.h"
using namespace std;
const  int N =30001;
int a[N];
int main()
{
    int n;
    int w;
    cin>>w>>n;
    for(int i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
    }
    std::sort(a,a+n);
    int ans=0;
    for(int i=0,j=n-1;i<=j;)
    {
        for(;i<j;j--)
        {
            if(a[i]+a[j]<=w)
                break;
            else ans++;
        }
        if(i!=j)
        {
            i++;j--;
            ans++;
        }
        else
        {
            ans++;
         break;
        }



    }
    cout<<ans;
    return 0;
}

C:

#include <stdio.h>
void qsort(int i,int j);
int a[30000];
void qsort(int i,int j){     
int x,p,q;    
 x=a[i]; p=i; q=j;    
  while (i<j)     {           
  while ((i<j)&&(a[j]>x))
   j--;         
    if (i<j)          
     {             
      a[i]=a[j];             
       i++;          
        }           
        while ((i<j)&&(a[i]<x))
         i++;           
         if (i<j)           
         {              
         a[j]=a[i];              
         j--;          
          }     
          }     
          a[i]=x;     
          if (p<i-1) 
          qsort(p,i-1);     
          if (i+1<q) 
          qsort(i+1,q);}
          main(){      
          int n,w,s,i,j;     
           scanf("%d%d",&w,&n);     
            for (i=0;i<n;i++) 
            scanf("%d",&a[i]);      
            qsort(0,n-1);      
            i=0;
             j=n-1; 
             s=0;     
             while (i<j)     
              {           
               s++;           
                if (a[i]+a[j]<=w)           
                 {              
                  i++;              
                   j--;           
                    }            
                    else j--;     
                     }      
                     if ((i==j)&&(a[i]<=w)) 
                     s++;       
                     printf("%d",s);     
                      getchar();      
                      getchar();     
                       return(0);
                       }

Java:

import java.io.*;
import java.util.Arrays;
public class Main {
    static int a[]=new int[30001];
    public static void main (String args[])throws IOException{
        BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
        int w=Integer.parseInt(bf.readLine());
        int n=Integer.parseInt(bf.readLine());
        for(int i=1;i<30001;i++)
            a[i]=999999;
        int k=n;
        int sum=0;
        for(int i=1;i<=n;i++)
        a[i]=Integer.parseInt(bf.readLine());
        Arrays.sort(a);
        oter:for(int i=1;i<=n;i++){
            for(int j=n;j>0;j--){
                if(k==i){
                    sum++;
                    break oter;
                }
                if(k-i==1&&a[i]+a[k]>w){
                    sum+=2;
                    break oter;
                }
                if(k-i==1&&a[i]+a[k]<=w){
                    sum++;
                    break oter;
                }
                if(a[i]+a[k]>w){
                    k--;
                    sum++;
                    }
                else{
                    sum++;
                    k--;
                    break;
                }
            }
        }
        System.out.println(sum);

    }
}

上面的Java代码是参考资料里的,下面是我自己的写的,感觉思路比较简单吧,能运行出来结果

import java.util.Scanner;
import java.util.Arrays;


import java.util.ArrayList;
public class 纪念品分组 
{
    public static void main(String[] args) 
    {
        Scanner sc = new Scanner (System.in);
        int max = sc.nextInt(); //纪念品和的上限
        int n = sc.nextInt();   //纪念品组数
        int[] arr = new int[n];
        for (int i=0; i<n; i++)     //遍历存储纪念品的价格
        {
            arr[i] = sc.nextInt();
        }
        Arrays.sort(arr);   //纪念品价格排序
        int min = arr[0];   //价格最小值
        int temp = max - min;       //中间变量:价格上限和最小值的差值
        int count = 0;
        int count1 = 0;
        int count2 = 0;
        for (int i=0; i<n; i++)
        {
            if (arr[i] > temp)
            {
                count++;        //单独一组的数量
            }
            if (arr[i] == min)
            {
                count1++;       //最小值的数量
            }
            if (arr[i] == temp)
            {
                count2++;       //能与最小值凑成一组刚好等于价格上限的数量
            }
        }
        int a = Math.min(count1, count2);       //价格之和等于价格上限的组数

        if ((n - count - 2*a)%2 == 0)       //判断剩余的是否能刚好分成两件一组
        {
            count = count + a + (n - count - 2*a)/2;
        }
        else
            count = count + a + (n - count - 2*a)/2 + 1;

        System.out.println(count);
    }
}