陣列分段和最大值最小問題
阿新 • • 發佈:2019-01-01
原始問題:
假設有m個房間,清潔每個房間耗時用一個數組表示,10、20、30、40、50、60、70、80、90,安排n個清潔工,將連續的房間分成n份,每部分耗時求和,其最大值為此種分法的總耗時。求最快的耗時是多少。例如3個清潔工的話,10 20 30 40 50 | 60 70 | 80 90,此時是最快的,耗時為170。
分析:
此題可以想象成把資料按順序裝入桶中,m即是給定的桶數,問桶的容量至少應該為多少才能恰好把這些數裝入n個桶中(按順序裝的)。
二分法思想求解:
首先我們可以知道,桶的容量最少不會小於陣列中的最大值,即桶容量的最小值(小於的話,這個數沒法裝進任何桶中),假設只需要一個桶,那麼其容量應該是陣列所有元素的和,即桶容量的最大值;其次,桶數量越多,需要的桶的容量就可以越少,即隨著桶容量的增加,需要的桶的數量非遞增的(二分查詢
#include<iostream> using namespace std; int getMax(int A[], int n) { int max = -1; for (int i = 0; i < n; i++) { if (A[i]>max) max = A[i]; } return max; } int getSum(int A[], int n) { int sum = 0; for (int i = 0; i < n; i++) { sum += A[i]; } return sum; } int getRequiredNum(int A[], int n, int MaxPer) { int num_bucket = 1; //至少需要一個桶 int sum = 0; for (int i = 0; i < n; i++) { sum += A[i]; if (sum>MaxPer) //超出桶容量 { sum = A[i]; num_bucket++; } } return num_bucket; } int BinarySearch(int A[], int n, int k) { int low = getMax(A, n); int high = getSum(A, n); while (low<high) //找到桶容量的範圍 { int mid = (low + high) / 2; int result = getRequiredNum(A, n, mid); if (result > k) //所需桶數量大於實際有的,需要增加容量 { low = mid + 1; } else //result<=k,嘗試減小容量 { high = mid; } } return low; }