poj_3273_Monthly Expense(二分搜索,最小花费)

Monthly Expense
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 32155 Accepted: 12113

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 
Lines 2.. N+1: Line  i+1 contains the number of dollars Farmer John spends on the  ith day

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

Hint

If Farmer John schedules the months so that the first two days are a month, the third and fourth are a month, and the last three are their own months, he spends at most $500 in any month. Any other method of scheduling gives a larger minimum monthly limit.

Source


题意:

最小化最大值问题,与最大化最小值问题刚好相反。。。。。
https://www.cnblogs.com/Sunnie69/p/5423817.html    点击打开链接,参考来源
共n个月,给出每个月的开销.将n个月划分成m个时间段,求m个时间段中开销最大的时间段的最小开销值.
分析:(这个问题与那个牛放入牛栏中的问题刚好相反,一个最小最大,一个最大最小,之前的博客https://blog.csdn.net/chrishuimin/article/details/79871676   点击打开链接

1.最大化最小值:
  相当于n个东西分给m个人,使得每个人至少拿x个,那么每个人拿够了就走,给后面的人多留一点,只要能分够>=m个人就是true,
多的全扔给最后一个人就是了.

2.最小化最大值:
  相当于n个东西分给m个人,每个人至多能拿x个,那么每个人尽可能多拿一点,给后面的人少留一点,只要能使<=m个人分完这n个东
西就是true,之后每个人随便拿一点给没有拿到的人就是了.

最小化最大值问题:
1.即首先求出二分的上下限,这个是每次二分必做的准备工作,上限即为这一堆东西的总量,下限即单个最大的物品的值。
2.有上下限之后即开始二分,最难写的部分就出来了,即判断当前分堆是否合理,在判断分堆是否合理中,主要的限制因素
   为两个,一个是单堆的量肯定不能超过当前的Mid值,另一个是分出的堆数一定不能超过题目要求的M值。
3.由判断条件即可将二分范围进行缩小,即,一旦当前Mid值满足分堆要求,意味着我还可以把Mid值缩小,即把二分的
   right=mid,如果当前Mid值触犯了判断条件,即说明当前值还太小,即把left=mid。
4.由以上二分return出来的结果即为所求值

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int Max = 100005;
const int inf = 100005;
int n,m;
int maxx = 0;
int x[Max];
bool C(int k)//区间的最小花费为k(类似牛的问题)
{
    int sum = 0,num = 1;
    for(int i=0;i<n;i++)    //n个月的开销
    {
        sum = sum + x[i];    //分区间(如果一个区间的和大于k了,就要从新开始新的区间求和)
        if(sum > k)  //这个区间的和大于k(最小花费了)
        {
            sum = x[i];  //再开始下一个区间,初始化sum的值。
            num ++;       //记录分成的区间个数
        }
    }
    if(num <= m)      //最后分成的区间个数
        return true;
    return false;
}
void solve()
{
    int left = maxx ,right = inf;
    while(left < right)
    {
        int mid = (left + right)/2;
        if(C(mid))
            right = mid;
        else
            left = mid+1;
    }
    printf("%d\n",left);
}
int main()
{
    scanf("%d%d",&n,&m);   //n个月,m个时间段(类似m头牛)

    for(int i=0;i<n;i++)
    {
        scanf("%d",&x[i]);     //输入n个月的花费
        maxx = max(maxx,x[i]);   //找出其中最大的花费
    }

    //sort(x,x+n);   //为什么不排序????
    solve();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值