zoukankan      html  css  js  c++  java
  • 二分搜索(二)——(最小值最大化和最大值最小化)

      有一类常见问题叫做最小值最大化或者最大值最小化。这类问题一般是用二分搜索来解决。

      首先二分搜索解决的问题必须具备单调性这个性质,这是使用二分搜索的必要条件,我们分析两个问题。

      1.最小值最大化:我们假设x为最大的最小值,那么x-1是满足条件的,但他并不满足最大,x+1是不满足条件的,假设我们左边界是L,右边界是R,我们二分一个答案ans,ans为最后一个满足条件的数,我们是不是可以类比二分搜索(一)中的last_less_equal()或者last_less()这个问题和这两者是差不多的。可以先阅读我的另一篇博文:二分搜索(一)——各种二分

      2.最大值最小化:我们假设x为最小的最大值,那么x-1是不满足条件的,x+1是满足条件的,但他不满足最小,假设我们左边界是L,右边界是R,我们二分一个答案ans,ans为第一个满足条件的数,我们是不是可以类比二分搜索(一)中的lower_bound()或者upper_bound()这个问题和这两者是差不多的。

      所以综上所述并根据我在二分搜索(一)——各种二分中的描述:最小值最大化的二分区间是右闭左开(L,R],每次二分的中心为M=(L+R+1)/2;最大值最小化的二分区间是左闭右开,[L,R),每次二分的中心为M=(L+R)/2。

      例题1:LA3971-3971——Assemble

       题目意思:你有b块钱,想要组装一台电脑。给出n个配件格子的种类,品质因子和价格,要求每种类型的配件各买一个,总价格不超过b,且品质最差的配件的品质因子尽量大。

       思路:这很明显是一个最小值最大化的问题,这道题还用到map对物品按名称进行分类,注意多组输入,要对上一组的数据进行清空,我们可以看出二分边界L=-1,R=maxq(所有商品中品质因子的最大值。),也就是右闭左开区间(L,R],我们搜索最后一个满足条件的ans值,具体看代码吧。

       代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1000+7;
    map<string,int>mp;
    struct node{
        int p,q;    
    };
    vector<node>a[N];
    int cnt=0,n,b;
    int check(int M){
        long long sum=0;
        for(int i=0;i<cnt;i++){
            int minn=b+10;
            for(int j=0;j<(int)a[i].size();j++){
                if(a[i][j].q>=M){
                    minn=min(minn,a[i][j].p);
                }
            }
            sum+=minn;
            if(sum>b) return 0;
        }
        return 1;
    }
    int main(){
        int T;cin>>T;
        while(T--){
            cin>>n>>b;    
            for(int i=0;i<cnt;i++) a[i].clear();
            cnt=0;
            int L=-1,R=0;
            for(int i=0;i<n;i++){
                string type,name;
                int p,q;
                cin>>type>>name>>p>>q;
                if(mp.count(type)==0){
                    mp[type]=cnt++;
                }
                R=max(R,q);
                a[mp[type]].push_back({p,q});
            }
            while(L<R){
                int M=(L+R+1)/2;
                if(check(M)) L=M;
                else R=M-1;
            }
            cout<<R<<endl;
        }
        return 0;
    }
    View Code

       

      例题2:openjudge-2456——Aggressive cows

        题目意思:农民约翰有用C只牛,然后他有N个隔间,每个隔间都有自己的坐标位置(一维的)pos,如何安排把牛安排进隔间才能使,所有牛之间距离的最小值最大,我们不需要求这个分配方案,我们只需要求这个最小距离的最大值,很裸的最小值最大化。

        思路:直接看代码吧

        代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=1e5+7;
    LL n,c,a[N];
    int check(int M){
        LL t=c-1,pre=0;
        for(int i=1;i<n;i++){
            if(a[i]-a[pre]>=M){
                t--;
                pre=i;
            }
            if(t==0) break;
        }
        return t==0;    
    }
    int main(){
        cin>>n>>c;    
        long long minn=0x3f3f3f3f,maxx=-0x3f3f3f3f;
        for(int i=0;i<n;i++){
            cin>>a[i];
            minn=min(a[i],minn); maxx=max(a[i],maxx);
        }
        sort(a,a+n);
        int L=0,R=maxx-minn;    
        while(L<R){
            int M=(L+R+1)/2;
            if(check(M)) L=M;
            else R=M-1;
        }
        cout<<R<<endl;
        return 0;
    }
    View Code

      例题3:openjudge-4135——Monthly Expense

       题目意思:共n个月,给出每个月的开销.将n个月划分成m个时间段,求m个时间段中开销最大的时间段的最小开销值。

       思路:最大值最小化,直接看代码吧

       代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m;
    vector<int>a;
    int check(int M){
        int ct=0,now=0;
        for(int i=0;i<n;i++){
            if(a[i]>M) return 0;
            if(now+a[i]>M){
                ct++;
                now=0;    
            }    
            now+=a[i];
        }
        return ct<m;
    }
    int main(){
        cin>>n>>m;
        a.resize(n);
        int R=0,L=0;
        for(int i=0;i<n;i++){
            cin>>a[i];
            R+=a[i];
            L=max(L,a[i]);
        }
        R++;    
        while(L<R){
            int M=(L+R)/2;
            if(check(M)) R=M;
            else L=M+1;
        }
        cout<<L<<endl;
        return 0;
    }
    View Code

     

     

     

  • 相关阅读:
    Vue单页面应用
    MVVM模式理解
    Ajax原生四大步骤
    Vue 全家桶介绍
    原生js的dom操作
    vs2015+opencv3.3.1+ maxflow-v3.01 c++实现Yuri Boykov 的Interactive Graph Cuts
    c++迭代递归实现汉诺塔(5种迭代方法满足你)
    opencv3.3.1+vs2015+c++实现直接在图像上画掩码,保存掩码图片
    声明函数指针、回调函数、函数对象------c++程序设计基础、编程抽象与算法策略
    C++/C语言的标准库函数与运算符的区别new/delete malloc/free
  • 原文地址:https://www.cnblogs.com/xiaowuga/p/8609943.html
Copyright © 2011-2022 走看看