3273 -- Monthly Expense (poj.org)
Language:Default Monthly Expense
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 Line 1: Two space-separated integers: N and M Output Line 1: The smallest possible monthly limit Farmer John can afford to live with. Sample Input 7 5 100 400 300 100 500 101 400 Sample Output 500 |
我直接上疑惑的点!
这是最大值最小化的图
这种题反其道而行之,把有可能的最小值最大值找出来(非常简单),然后在这个范围内二分求满足题意的区间个数,需要注意的是左边是不可行解,右边是可行解但不是最优解,所以要逐步逼近找到临界点那个临界点必然是满足题意且真实存在的点。
AC CODE
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
int a[100010];
int N, M;
bool func(int mid)
{
int sum = 0;
int len = 1;
for (int i = 1; i <= N; i++)
{
if (sum + a[i] <= mid)
sum += a[i];
else
{
sum = a[i];
len++;
}
}
if (len > M)
return false;
else
return true;
}
int main()
{
cin >> N >> M;
double left = 0, right = 0;
for (int i = 1; i <= N; i++)
{
cin >> a[i];
right += a[i];
if (a[i] > left)
left = a[i];
} //OK
int mid;
while (left <= right)
{
mid = (left + right) / 2;
if (func(mid) == false)
{
left = mid + 1;
}
else
right = mid - 1;
}
cout << mid << endl;
}