给定一个整型数组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))