题解
题目难度:中等难度
知识点:二分法、查找、数组
首先考虑:这是一道查找题,可确定最小值的范围,再使用方法逐渐逼近这个最优解。
二分法逼近最小值
首先明确这个最小值一定是介于(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; }