牛客算法周周练4 E题装备合成——三分搜索

  • 链接 :装备合成
  • 题意 :
    在这里插入图片描述
  • 思路 :控制变量
    设 方法一生成的装备数量为 m,则方法二生成的装备数量是
    min((x - 2 * m)/4, y - 3* m)。
    所以生成的总量函数 f(m) = m + min((x - 2 * m)/4, y - 3* m)。
    m 的范围是 [0, min(x/2,y/3) ] ,即使用方法一生成的个数。而直接线性维护此函数的极值,复杂度最高是 1e9/2,所以需要用二分或者三分搜索极值,这就要观察此函数是递增(递减)或者凹凸函数。

(1)打表观察此函数

#include "bits/stdc++.h"
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
typedef long long ll;
const int maxn = 1e4 + 7;
const int INF = INT_MAX;
const double EPS = 10;
#define _DEBUG
int t, x, y;
int func(int mid){
    
    
    return mid + min((x - 2 * mid)/4, y - 3* mid);
}
int main(){
    
    
#ifdef _DEBUG
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>t;
    while (t--) {
    
    
        cin>>x>>y;
        for (int i = 0; i <= min(x/2,y/3); i++) {
    
    
            cout<<func(i)<<endl;
        }
    }
    return 0;
}

给定x = 1000, y = 1000,输出此函数的值
截取一部分:
在这里插入图片描述
可知此函数是凸函数。

(2)三分搜索
如果三分搜索不懂,可以看这个博客三分搜索

#include "bits/stdc++.h"
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
typedef long long ll;
const int maxn = 1e4 + 7;
const int INF = INT_MAX;
const double EPS = 10;
#define _DEBUG
int t, x, y;
int func(int mid){
    
    
    return mid + min((x - 2 * mid)/4, y - 3* mid);
}
int main(){
    
    
#ifdef _DEBUG
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>t;
    while (t--) {
    
    
        cin>>x>>y;
        int l = 0, r = min(x/2, y/3);
        while (r - l > EPS) {
    
    
            int mid1 = l + (r-l)/3;
            int mid2 = r - (r-l)/3;
            if (func(mid1) < func(mid2)) {
    
    
                l = mid1;
            }else{
    
    
                r = mid2;
            }
        }
        int ans = 0;
        for (int i = l; i <= r; i++) {
    
    
            ans = max(ans, func(i));
        }
        cout<<ans<<endl;
    }
    return 0;
}

  • 遇到的问题:
    (1)首先是这个函数没写出来,应该控制变量,设方法一生成的m件,再求方法二的。则这个函数自变量是m,三分搜索对m即可。
    (2)EPS的设置。刚开始将EPS设置为1,复杂度超过了。
    我们此题用到三分搜索的目的是,缩减区间,代码中设置r - l > 10,最后在l——r中维护一个max值即可。一般来说只有double类型的题目,才能精准确定极值。
    具体视情况而定,我博客中其他几个三分搜索double类型的,EPS设置为1e-12,最后 l 即是驻点;而此题则缩减一定区间即可,EPS = 10遍很快乐。

Guess you like

Origin blog.csdn.net/qq_39763472/article/details/105845213