1. 程式人生 > >1023 修路 二分+模擬

1023 修路 二分+模擬

題目描述
前段時間,某省發生乾旱,B山區的居民缺乏生活用水,現在需要從A城市修一條通往B山區的路。假設有A城市通往B山區的路由m條連續的路段組成,現在將這m條路段承包給n個工程隊(n ≤ m ≤ 300)。為了修路的便利,每個工程隊只能分配到連續的若干條路段(當然也可能只分配到一條路段或未分配到路段)。假設每個工程隊修路的效率一樣,即每修長度為1的路段所需的時間為1。現在給出路段的數量m,工程隊的數量n,以及m條路段的長度(這m條路段的長度是按照從A城市往B山區的方向依次給出,每條路段的長度均小於1000),需要你計算出修完整條路所需的最短的時間(即耗時最長的工程隊所用的時間)。

Input
第一行是測試樣例的個數T ,接下來是T個測試樣例,每個測試樣例佔2行,第一行是路段的數量m和工程隊的數量n,第二行是m條路段的長度。

Output
對於每個測試樣例,輸出修完整條路所需的最短的時間。

Sample Input
2
4 3
100 200 300 400
9 4
250 100 150 400 550 200 50 700 300
Sample Output
400
900

題目大意:就是m條路段承包給n個工程隊(n ≤ m ≤ 300),給出每一條路的長度,路多長就代表花多長時間來修這條路,可以有的工程隊不修路,但是不能有工程隊“跨路修路”,一條路只能給一個工程隊修,求修路最短時間

思路:修這m條路的最長時間就是所有的路段之和,最短時間就是m條路的最大值。然後把最小值到最大值之間的值二分模擬一下。在某個時間mid內,如果工程隊用完了,但是路還沒有修完,說明這個時間不滿足,應該low=mid+1;如果路修完了,但是工程隊還沒有使用完,那說明high=mid;
二分多想想邊界值

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cctype>
using namespace std;
int m,n;
int a[310];

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&m,&n);
        int left = 0,right = 0 , mid;
        for(int i = 0
; i < m ; ++i){ scanf("%d",&a[i]); if(left < a[i]) left = a[i]; right += a[i]; } int use; while(left < right){ use = 0; mid = (left + right) /2; int temp = 0; for(int i = 0 ; i < m ; ++i){ temp += a[i]; if(temp > mid){ temp = a[i]; use++; } } if(use <= n - 1){ right = mid; } else if(use > n-1){ left = mid+1; } } printf("%d\n",left); } return 0; }