给定一个整型数组arr, 数组中的每个值都为正数,表示完成一幅画作需要的时间,再给定一个整数num,表示画匠的数量,每个画匠只能画连在一起(即数组内连续的一段)的画作。所有画家并行工作,请返回完成所有的画作的最少时间。
[要求]
时间复杂度为
(其中S表示所有画作所需时间的和)
第一行两个整数N, K表示数组大小,画匠的数量。
接下来一行N个整数表示完成每幅画作所需要的时间。
输出一个整数表示答案
3 2 3 1 4
4
最好的分配方式为第一个画匠画3和1,所需时间为4,第二个画匠画4,所需时间为4。因为并行工作,所以最少时间为4,如果分配方式为第一个画匠画3,所需时间为3,第二个画匠画1和4,所需的时间为5,那么最少时间为5,显然没有第一种分配方式好,所以返回4
5 3 1 1 1 4 3
4
最好的分配方式为第一个画匠画前三个1,所需时间为3,第二个画匠画4,所需时间为4,第三个画匠画3,所需时间为3,返回4
5 2 99 82 44 35 3
164
[99] [82 44 35 3]
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] params = br.readLine().split(" ");
int n = Integer.parseInt(params[0]), k = Integer.parseInt(params[1]);
params = br.readLine().split(" ");
int[] time = new int[n];
long lb = 0, ub = 0; // 二分的边界
for(int i = 0; i < n; i++) {
time[i] = Integer.parseInt(params[i]);
lb = Math.max(time[i], lb);
ub += time[i];
}
while(lb < ub){
long h = lb + ((ub - lb) >> 1); // 花费h小时
if(getPainterNums(h, time) <= k)
ub = h; // 限制在h小时,只需要不超过k个画家就能做到,可以压缩上界
else
lb = h + 1;
}
System.out.println(ub);
}
// 计算h小时完成所有画作需要的画家数
private static int getPainterNums(long h, int[] time) {
long partTime = 0;
int parts = 1;
for(int i = 0; i < time.length; i++){
if(partTime + time[i] <= h){
partTime += time[i]; // 这一部分凑h的时长
}else{
partTime = time[i]; // 超过h的时长,需要加一位画家
parts ++;
}
}
return parts;
}
} #include <bits/stdc++.h>
#define ll long long
using namespace std;
int main(){
int n, k;
cin>>n>>k;
ll a[n+1], x, Max=0;
for(int i=0;i<n;i++){
cin>>a[i];
Max = max(Max, a[i]);
}
ll l = Max, r = INT64_MAX>>2, m, s, cnt;
while(l<r){
s = cnt = 0;
m = (l+r)>>1;
for(int i=0;i<n;i++){
if(m < s+a[i]){
s = a[i];
cnt++;
}else
s += a[i];
}
if(s)
cnt++;
if(cnt > k)
l = m+1;
else
r = m;
}
cout<<l<<endl;
return 0;
} def solution(arr, num): # 工作清单和工人数目 | O(N*logS), S=sum(arr)
assert arr and len(arr) and num
if len(arr) <= num: # 如果工人过多,则是取最长的一个工作返回
return max(arr)
def get_need_num(limit): # 每个画师只能工作不超过limit的时间,问需要几个画师才能完成
res, worked = 1, 0 # 已用画师数目, 当前画师已工作时间
for v in arr:
if v > limit: # 这一幅画哪怕单独分配给一个画师也完成不了
return float('inf')
worked += v
if worked > limit: # 如果尝试画当前的画已超工时
res += 1 # 新增一个画师来画这幅画
worked = v # 新增画师的当前工时为v
return res
min_sum, max_sum = 0, sum(arr) # 二分法确定每个画师的最大工作量
while min_sum != max_sum - 1:
mid = (min_sum + max_sum) // 2
if get_need_num(mid) > num:
min_sum = mid
else:
max_sum = mid
return max_sum
n, num = map(int, input().split())
arrs = list(map(int, input().split()))
print(solution(arrs, num))