zoukankan      html  css  js  c++  java
  • POJ3273-Monthly Expense (最小化最大值)

    题目链接click here~~

    【题目大意】

     农夫JF在n天中每天的花费,要求把这n天分作m组。每组的天数必定是连续的。要求分得各组的花费之和应该尽可能地小,最后输出各组花费之和中的最大值

    【解题思路】:

    经典的最小化最大值问题,要求连续的m个子序列,子序列的和最大值的最小,枚举满足条件的m的最小值即为答案。因此二分查找。

    1.能否把序列划分为每一个序列之和不大于mid的m个子序列,
    2.通过用当前的mid值能把天数分成几组,
    3.比較mid和t的大小,从而确定mid

    详细见代码吧:

     
    //#include <bits/stdc++.h>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int N=1e5+10;
    int n,m,num[N];
    bool is_part(int mid)
    {
        int t=0,s=0;     //t==当前mid值能把n天分成的组数(初始把所有天数作为0组)     
        bool ok=true;
        for(int i=0; i<n; i++)//遍历每一天的花费
        {
            if(num[i]>mid){//假设某个值大于,显然不符合
                ok=false;
                break;
            }
            if(s+num[i]>mid){//不能再把当前元素加上了
                t++;
                s=num[i];    //把前i天作为一组
                if(t>m-1){   //t=m时退出。即在最后一个元素之前都已经用了m条划分线
                    ok=false;
                    break;
                }
            }
            else s+=num[i];//把当前元素与前面的元素加上。以便尽量往右划分,贪心究竟
        }
        return ok;
    }
    void judge()          //二分查找
    {
        int ll=0,rr=1e8;
        while(ll<rr)
        {
            int mid=(ll+rr)>>1;
            if(is_part(mid)) rr=mid;
            else ll=mid+1;
        }
       printf("%d
    ",ll);
    }
    int main()
    {
        int maxx=0,sum=0;
        scanf("%d%d",&n,&m);
        for(int i=0; i<n; i++){
            scanf("%d",&num[i]);
            sum+=num[i];
            maxx=max(maxx,num[i]);
        }
        if(m==n||m==1) printf("%d
    ",maxx);
        else judge();
        return 0;
    }

  • 相关阅读:
    wx_sample.php

    手机装linux系统
    MySQL导入导出命令
    PHP对表单提交特殊字符的过滤和处理
    sublime开启php自动代码补全
    寻找Linux单机负载瓶颈
    怎样成为PHP 方向的一个合格的架构师
    说说大型高并发高负载网站的系统架构
    数据库水平分割,垂直分割,库表散列浅谈
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5325115.html
Copyright © 2011-2022 走看看