zoukankan      html  css  js  c++  java
  • 最大值最小化问题

    问题描述:

    把一个包含n个正整数的序列划分成m个连续的子序列。设第i个序列的各数之和为S(i),求所有S(i)的最大值最小是多少?

    例如序列1 2 3 2 5 4划分为3个子序列的最优方案为 1 2 3 | 2 5 | 4,其中S(1),S(2),S(3)分别为6,7,4,那么最大值为7;

    如果划分为 1 2 | 3 2 | 5 4,则最大值为9,不是最小。

    问题分析:

    能否使m个连续子序列所有的s(i)均不超过x,则该命题成立的最小的x即为答案。该命题不难判断,只需贪心,每次尽量从左

    向右尽量多划分元素即可。

    我们把该问题转化为递归分治问题,类似于二分查找。首先取Sum和元素最大值的中值x,如果命题为假,那么答案比x大;

    如果命题为真,则答案小于等于x。问题得解,复杂度为O(n*logSum)

    代码:

    #include<iostream>
    #include<vector>
    
    using namespace std;
    
    int divide = 3;
    
    int main()
    {
        vector<int> a = { 9, 19, 15, 13, 13, 9, 14, 1, 1, 7 };
        int max = INT_MIN;
        int sum = 0;
        for (int i = 0; i < a.size(); i++)
        {
            if (max < a[i])
            {
                max = a[i];
            }
            sum += a[i];
        }
        int left = max;
        int right = sum;
        int min = INT_MAX;
        while (left < right)
        {
            int middle = (left + right) / 2;
            int m = 0;
            int n = 0;
            int i;
            for (i = 0; i < a.size(); i++)
            {
                m += a[i];
                if (m<=middle)
                    continue;
                m = a[i];
                n++;
            }
            n++;
            if (n <= divide)
            {
                if (middle < min)
                    min = middle;
                right = middle - 1;
            }
            else
                left = middle + 1;
        }
        cout << min << endl;
    }
  • 相关阅读:
    常用资源
    printf打印颜色
    Vue开发中踩坑-Day3
    Vue开发踩坑-Day2
    Vue开发中的踩坑-day1
    Python中virtualenv的使用
    第十一章:Python高级编程-协程和异步IO
    第十章:Python高级编程-多线程、多进程和线程池编程
    第九章:Python高级编程-Python socket编程
    自定义Element父子不关联的穿梭树
  • 原文地址:https://www.cnblogs.com/chaiwentao/p/4483584.html
Copyright © 2011-2022 走看看