zoukankan      html  css  js  c++  java
  • 三分法+例题(CF1355E

    在一个非单调函数中来确定其最值的方法

    模板

    整数的三分

    int l = 1,r = 100;
    while(l < r) {
        int lmid = l + (r - l) / 3;
        int rmid = r - (r - l) / 3;
        lans = f(lmid),rans = f(rmid);
        // 求凹函数的极小值
        if(lans <= rans) r = rmid - 1;
        else l = lmid + 1;
        // 求凸函数的极大值
        if(lans >= rans) l = lmid + 1;
        else r = rmid - 1;
    }
    // 求凹函数的极小值
    cout << min(lans,rans) << endl;
    // 求凸函数的极大值
    cout << max(lans,rans) << endl;
    

    浮点数的三分

    const double EPS = 1e-9;
    while(r - l < EPS) {
        double lmid = l + (r - l) / 3;
        double rmid = r - (r - l) / 3;
        lans = f(lmid),rans = f(rmid);
        // 求凹函数的极小值
        if(lans <= rans) r = rmid;
        else l = lmid;
        // 求凸函数的极大值
        if(lans >= rans) l = lmid;
        else r = rmid;
    }
    // 输出 l 或 r 都可
    cout << l << endl;

    题目链接

    https://codeforces.ml/problemset/problem/1355/E

    题目大意:给你四个数N,A,R,M,其中N表示一共有N列墙,每列墙拥有的砖块数是h[i],你需要通过增减砖块使每列墙的砖块数相同,可以进行三个操作:1、花费A,在某列墙上放一块砖,2、花费R,在某列墙中拿掉一块,3、花费M,将某一列墙中的一块放到令一列墙中。问你最少需要花费多少。

    解题思路:首先写出一个count 函数,计算将墙都变为x块砖最少需要多少花费。利用三分法求这个函数在区间内的极小值。

    代码

    #include<bits/stdc++.h>
    #define ll long long
    #define MOD 1000000007  
    #define INF 0x3f3f3f3f
    #define mem(a,x) memset(a,x,sizeof(a))  
    #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    using namespace std;
    ll h[100005];
    ll N,A,R,M;
    ll count(ll x)
    {
         ll d=0,s=0;
         ll sum=0;
         for(int i=1;i<=N;i++){
             if(h[i]>x){
                d+=h[i]-x;
             }else{
                s+=x-h[i];
             }
         }
         if(M<A+R){
            ll p=min(d,s);
            sum+=M*p;
            d-=p;
            s-=p;
            if(d!=0){
               sum+=R*d;
               d=0;
            }
            if(s!=0){
               sum+=A*s;
            }
         }else{
            sum+=A*s;
            sum+=R*d;
         }
         return sum;
    }
    int main()
    {
        cin>>N>>A>>R>>M;
        ll maxn=0;
        for(int i=1;i<=N;i++){
           scanf("%lld",&h[i]);
           maxn=max(h[i],maxn);
        }
        ll l=0,r=maxn;
        ll lans,rans;
        while(l<r)
        { 
             ll lmid=l+(r-l)/3;
             ll rmid=r-(r-l)/3;
             lans=count(lmid),rans=count(rmid);
             //cout<<lmid<<" "<<rmid<<endl;
             if(lans>rans)l=lmid+1;
             else r=rmid-1;
             //cout<<l<<" "<<r<<endl;
        }
        cout<<min(lans,rans);
        return 0;
    }
    越自律,越自由
  • 相关阅读:
    谢尔排序(缩小增量排序)
    折半插入排序
    插入排序
    选择排序
    冒泡排序
    ul+js模拟select+改进
    ul+js模拟select
    前端面试题
    js数组去重的三种常用方法总结
    使用PHP实现文件上传和多文件上传
  • 原文地址:https://www.cnblogs.com/ha-chuochuo/p/13435581.html
Copyright © 2011-2022 走看看