Dichotomous maximization problem (1)

binary optimization problem

Divide a sequence of n positive integers into m consecutive subsequences (each positive integer belongs to exactly one sequence).

Let the sum of the numbers of i sequences be s(i). Your task is to make the maximum value of all s(i) as small as possible.

This algorithm is very practical. It takes a lot of technology to divide a bunch of messy things into a pile, and the divided things do not exceed a fixed value.

1. First determine the upper and lower bounds of the bisection, which is the preparatory work that must be done for each bisection. Here the upper limit is the total amount of this pile of things, and the lower limit is the value of the single largest item.

2. After the upper and lower limits are determined, the bisection begins. That is In judging whether the current stacking is reasonable, and then judging whether the stacking is reasonable, there are two main limiting factors, one is that the amount of a single stack must not exceed the current mid value, and the other is that the number of separated stacks must not exceed the problem requirements. 3. The dichotomous
range can be narrowed by the judgment condition, that is, once the current mid value meets the stacking requirements , it means that I can also reduce (minimize) the mid value, that is, the right=mid of the dichotomy , if If the current mid value violates the judgment condition, set left=mid.

4. The result of the above binary return
is the evaluated value.

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N];
int ok(int m)
{
    int sum=0,cnt=0;
    for(int i=0;i<n;i++)
    {
        if(a[i] > m) return false;
        
        if(sum + a[i] > m)
        {
            cnt++;
            sum = a[i];
        }
        else sum+=a[i];
    }
    return cnt <= m;
}
int main()
{
    int n,k,sum=0;
    cin>>n>>k;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        sum+=a[i];          //r
        Max=max(Max,a[i);   //l
    }
    int l=Max,r=sum;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(ok(mid)) r=mid;
        else l=mid+1;
    }
    cout<<l<<endl;
}

Minimize the maximum


It is the exact opposite of the maximization-minimum problem, which is also solved by dichotomy, and the difference is mainly in the judgment condition.


1. Maximize the minimum value (and help the world)

It is equivalent to dividing n things to m people, so that each person takes at least x pieces , then everyone can leave if they have enough, and leave a little more for the people behind, as long as they can divide enough >=m people, it is true, and all the more are thrown away Just for the last person.

2. Minimize the maximum value (stand alone)


It is equivalent to dividing n things to m people, each person can get at most x pieces, then each person can get as much as possible, and leave a little less for the people behind, as long as <=m people can divide n things, it is true, then Everyone just takes a little bit and gives it to those who don't get it.


Notice:


1. Regarding the initial value, some questions directly give the prefix sum, so that the maximum value of the minimum value is the average value, and the minimum value of the maximum value is also the average value.
For the problems that can calculate the sum:

2. Maximize the minimum value:

x is the single-point minimum value, and y is the average value.

3. Minimize the maximum value:

x is the larger of the average value and the single-point maximum value, and y is the sum. In fact, you can directly set x=0, y=0x7fffffff, but the loop is only 32 times...

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325074007&siteId=291194637