CSU1976: 搬運工小明
Description
作爲老人的小明非常憂傷,因爲他馬上要被流放到本部去了,住進全左家壠最有歷史感的11舍真是一件非常榮幸的事情。
搬行李是個體力活,小明發現自己的行李太多啦,所以他決定去買很多個袋子來裝走。到了超市的小明發現,不同大小的袋子居然價格一樣???雖然買最大的自然最賺,但是小明是名遠近聞名的環保人士,他覺得袋子只要能裝下他的行李就夠了,並且爲了不麻煩收銀的小姐姐(⊙o⊙)…,他也只會購買同一種大小的袋子。因此他希望在能裝下所有行李的前提下,袋子越小越好。同時爲了避免弄亂行李,小明希望同一個袋子裝的是位置連續相鄰的行李。
小明摸了摸口袋發現自己帶的錢最多能買N個袋子,數學特別差的他不知道到底該買多大的才合適,所以想靠你來解決這個問題了。
Input
第一行爲一個數字T(T<=10)表示數據組數
第二行爲兩個數字N(N <= 10^5)和 M(M <= 10^5)表示袋子個數和小明的行李個數
第三行爲M個數字,第i個數字a[i]表示小明的第i個行李體積爲a[i](0<a[i] <= 10^9)
Output
輸出一行表示袋子的最小體積(整數)
Sample Input
1
3 3
1 1 1
Sample Output
1
Hint
袋子不能裝下體積大於其容積的物品
多個物品滿足體積之和小於等於一個袋子的容積,就能被裝進
Source
2017年8月月賽
Author
盧銘威
一道簡單二分題目。先假定所有物品全部裝入一個袋子,將這個袋子的體積作爲上界,對袋子的容積進行二分,直到得出最優答案。
一開始犯糊塗,設置了袋子過小時記錄mid,變成令袋子儘量大了,半天沒發現錯誤,耽誤了不少時間。以後做二分還是得頭腦清醒,多加註意。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
const long long maxn = 1e5+10, INF = 0xffffffff;
long long T, n, m;
long long luggage[maxn];
long long check(long long bagSize){
long long bagNum = 1, tempSum = 0;
for(long long i = 0; i < m; i++){
if(luggage[i] > bagSize)// 若某件物品體積比袋子容積還大,說明袋子太小,故認爲需要袋子的數量非常多,從而令下一次迭代的mid增大。
return n+1;
tempSum += luggage[i];
if(tempSum > bagSize){
tempSum = luggage[i];
bagNum++;
}
}
return bagNum;
}
int main(){
#ifdef TEST
freopen("test.txt", "r", stdin);
#endif // TEST
scanf("%lld", &T);
while(T--){
scanf("%lld%lld", &n, &m);
long long maxSize = 0;
for(long long i = 0; i < m; i++){
scanf("%lld", &luggage[i]);
maxSize += luggage[i];
}
long long left = 0, right = maxSize, mid, ans;
while(left <= right){
mid = (left + right) / 2;
if(check(mid) > n){// mid is too small
left = mid + 1;
}
else{// mid is too large or just it
ans = mid;
right = mid - 1;
}
}
printf("%d\n", ans);
}
return 0;
}
/**********************************************************************
Problem: 1976
User: xyJiang
Language: C++
Result: AC
Time:136 ms
Memory:2800 kb
**********************************************************************/