题解

题目难度:中等难度

知识点:二分法、查找、数组

首先考虑:这是一道查找题,可确定最小值的范围,再使用方法逐渐逼近这个最优解。

二分法逼近最小值

首先明确这个最小值一定是介于(max(nums),sum(nums))之间,因此我们可以使用二分查找来缩小范围。
第一步:先确定个mid=(sum+max)/2的值,以这个值为界限,
第二步:从左向右放入值,直到放入的值总和已经>mid,以此为一个分割划分为一个组,
第三步:再继续放入,一旦又大于mid则再次分割。
第四步:最后如果最后的组数大于要求划分的组数,说明mid值太小,这个最小值要比mid大,最小值处在(mid,sum)之间。否则处在(max,mid)之间。当然,如果组数等于要求的数时,最小值也可能还可以再小。

以示例说明:1 4 2 3 5 ;最大值5,和为15,Mid等于10。M表示所求的值

M值 第一组 第二组 第三组
10 1 4 2 3 5
10 1 4 2 3 5
10 1 4 2 3 5
10 1 4 2 3 5
7 1 4 2 3 5
7 1 4 2 3 5
7 1 4 2 3 5
7 1 4 2 3 5
6 1 4 2 3 5
6 1 4 2 3 5
6 1 4 2 3 5
6 1 4 2 3 5
5 1 4 2 3 5
5 1 4 2 3 5
5 1 4 2 3 5
5 1 4 2 3 5
#include <bits/stdc++.h>
using namespace std;
//创建一个判断函数,a[]保存这个数组,Mid表示这个值,n表示数字个数,m表示最多分为的组数
bool exist(int a[], int mid, int n, int m)
{
    int cnt = 1;
    int sum = 0;
    for (int i = 0;i < n;i++)
    {
        if (sum + a[i] <= mid)
            sum += a[i];
        else
        {
            sum = a[i];
            cnt++;
            if (cnt > m)
            {
                return false;
            }
        }

    }
    return true;
}
int main()
{
    int n, m, num, max = 0, sum = 0;
    cin>>n>>m;
    int a[n];
    for (int i = 0;i < n;i++)
    {
        int x;
        cin>>x;
        a[i]=x;
        if (a[i] > max)
        {
            max = a[i];
        }
        sum += a[i];
    }
    int mid;
    while (sum >= max)
    {
        mid = (max + sum) / 2;
        if (exist(a, mid, n, m))
        {
            sum = mid-1;
        }
        else
        {
            max = mid + 1;
        }
    }
    cout<<max<<endl;
}