Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 24563 | Accepted: 9550 |
Description
Farmer John is an astounding accounting wizard and has realized he might run out of money to run the farm. He has already calculated and recorded the exact amount of money (1 ≤ moneyi ≤ 10,000) that he will need to spend each day over the next N (1 ≤ N ≤ 100,000) days.
FJ wants to create a budget for a sequential set of exactly M (1 ≤ M ≤ N) fiscal periods called "fajomonths". Each of these fajomonths contains a set of 1 or more consecutive days. Every day is contained in exactly one fajomonth.
FJ's goal is to arrange the fajomonths so as to minimize the expenses of the fajomonth with the highest spending and thus determine his monthly spending limit.
Input
Lines 2.. N+1: Line i+1 contains the number of dollars Farmer John spends on the ith day
Output
Sample Input
7 5 100 400 300 100 500 101 400
Sample Output
500
Hint
题意:给出n个数,要求划分成m份,求每一份的总和的最大值的最小值,即最小化最大值,明显二分,即使二分不是很会,但是水水还是过了。
题解:即二分,二分答案的题目,首先必须有个判断答案是否正确的函数,下面代码为can(),然后在最小值答案和最大值答案之间进行二分,找到最小的答案,复杂度O(nlogn)。(最小值答案很明显就是分成n份的答案,最大值答案就是分成一份的答案)。
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <sstream>
#include <fstream>
#include <set>
#include <map>
#define INF 1e9
#define M_PI 3.14159265358979323846
using namespace std;
int n,m;
int s[100005];
bool can(int a)//判断函数,判断最小值为a时能否分为m份
{
int sum = 0,cnt = 0;
for (int i = 0;i < n;i++)
{
sum += s[i];
if(sum>a)
{
sum = s[i];
cnt++;
}
}
if(cnt+1>m)//当cnt+1比m大时,说明无法分成m份
return false;
else
return true;
}
int main()
{
//infile.open("1234.txt",ios::in);
while (cin>>n>>m)
{
int mos = 0,sum = 0;
for (int i = 0;i < n;i++){
cin>>s[i];
mos = max(mos,s[i]);
sum += s[i];
}
int lb = mos,ub = sum;
while(ub-lb>1)//二分查找
{
int mid = (ub+lb)/2;
if(can(mid)){
ub = mid;
}
else{
lb = mid+1;
}
}
if(can(lb)){
cout<<lb<<endl;
}
else
cout<<lb+1<<endl;
}
return 0;
}