分发巧克力问题

原文地址:Chocolate Distribution Problem

已知一个有n个整数的数组,数组中的每个值表示的是一个包裹中巧克力的数量。每个包裹都有一个表示巧克力数量的变量。这里有m个学生,按下面的规定把巧克力包裹分发出去:

  1. 每个学生都得到一个包裹;
  2. 给到学生的巧克力包裹含有的最大巧克力数目与最小巧克力数目的的差为最小。

例子:

输入: arr[] = {7, 3, 2, 4, 9, 12, 56} 
        m = 3
输出: 最小差是2

我们有七个巧克力包裹,并且需要选出3个给学生,如果我们选择2,3,4的话,那么我们就得到了最大包裹与最小包裹的最小差。

输入: arr[] = {3, 4, 1, 9, 56, 7, 9, 12} 
      m = 5
输出: 最小差是6
例如集合3,4,7,9,9,那么输出为9-3 = 6

输入: arr[] = {12, 4, 7, 9, 2, 23, 25, 41, 30, 40, 28, 42, 30, 44, 48, 43, 50} 
      m = 7
输出: 10

我们得选出7个包裹。选择40,41,42,44,48,4350得到最大值和最小值的差。

一个简单的方案就是生成所有大小为m的arr[0..n-1]的子集。对于每个子集,然后找出其中的最大值与最小值的差,最后返回最小的差。

另一个有效的方法就是基于观察来最小化差距,我们必须从有序的包裹中选择连续的元素,我们首先对arr[0..n-1]进行排序,然后找到大小为m的子集的最后一个元素与第一个元素的差的最小值。

// C++ program to solve chocolate distribution
// problem
#include<bits/stdc++.h>
using namespace std;

// arr[0..n-1] represents sizes of packets m is number of students.
// Returns minimum difference between maximum and minimum values of distribution.
int findMinDiff(int arr[], int n, int m)
{
    // if there are no chocolates or number
    // of students is 0
    if (m==0 || n==0)
        return 0;

    // Sort the given packets
    sort(arr, arr+n);

    // Number of students cannot be more than
    // number of packets
    if (n < m)
       return -1;

    // Largest number of chocolates
    int min_diff = INT_MAX;

    // Find the subarray of size m such that difference between last (maximum in case
    // of sorted) and first (minimum in case of sorted) elements of subarray is minimum.
    int first = 0, last = 0;
    for (int i=0; i+m-1<n; i++)
    {
        int diff = arr[i+m-1] - arr[i];
        if (diff < min_diff)
        {
            min_diff = diff;
            first = i;
            last = i + m - 1;
        }
    }
    return (arr[last] - arr[first]);
}

int main()
{
    int arr[] = {12, 4, 7, 9, 2, 23, 25, 41,
                 30, 40, 28, 42, 30, 44, 48,
                 43, 50};
    int m = 7;  // Number of students
    int n = sizeof(arr)/sizeof(arr[0]);
    cout << "Minimum difference is "
         << findMinDiff(arr, n, m);
    return 0;
}

输出:

Minimum difference is 10

时间复杂度是:O(nLogn),因为我们在子数组查询前做个了排序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值