【算法模板】数据结构:三分查找

算法竞赛中的三分(ternary search)是一种用于在单峰函数(unimodal function)上找到最大值或最小值的搜索算法。与二分搜索(binary search)类似,三分搜索在每次迭代中将搜索空间分成三个部分,但三分搜索用于连续区间而不是离散区间。

算法思想

三分搜索的基本思想是在给定的区间内通过选择两个点将区间分成三个部分,并根据函数值的比较逐步缩小搜索范围。它主要适用于单峰函数,即在某一范围内函数有一个唯一的最大值或最小值。

算法步骤

假设我们在区间 [l,r] 上寻找函数 f(x) 的最大值。三分搜索的步骤如下:

  1. 初始化:设定初始区间 [l,r]。
  2. 计算两个分点:在区间 [l,r] 上选择两个点 m1 和 m2,通常选择方法为: m1=l+(r−l)/3, m2=r−(r−l)/3
  3. 比较函数值:计算 f(m1)和 f(m2),并进行比较:
    • 如果 f(m1)<f(m2),说明最大值在区间 [m1,r]内,舍弃 [l,m1]。
    • 如果 f(m1)>f(m2),说明最大值在区间 [l,m2]内,舍弃 [m2,r]。
    • 如果 f(m1)=f(m2),则最大值在区间 [m1,m2]内,舍弃 [l,m1]和 [m2,r]。
  4. 更新区间:根据上述比较结果更新区间 [l,r]。
  5. 终止条件:重复步骤 2 至 4,直到区间长度小于某个预定的精度阈值 ϵ。

例题

P3382 三分

如题,给出一个 N 次函数,保证在范围 [l, r] 内存在一点 x,使得 [l, x] 上单调增,[x, r] 上单调减。试求出 x 的值。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

const double EPS = 1e-7;

// 计算多项式在 x 处的值
double polynomial_value(const vector<double>& coefficients, double x) {
    double value = 0.0;
    for (const auto& coeff : coefficients) {
        value = value * x + coeff;
    }
    return value;
}

// 三分搜索寻找极大值点
double ternary_search(const vector<double>& coefficients, double left, double right) {
    while (right - left > EPS) {
        double m1 = left + (right - left) / 3;
        double m2 = right - (right - left) / 3;
        double f1 = polynomial_value(coefficients, m1);
        double f2 = polynomial_value(coefficients, m2);
        if (f1 < f2) {
            left = m1;
        } else {
            right = m2;
        }
    }
    return (left + right) / 2;
}

int main() {
    int N;
    double l, r;
    cin >> N >> l >> r;
    vector<double> coefficients(N + 1);
    for (int i = 0; i <= N; ++i) {
        cin >> coefficients[i];
    }
    double x = ternary_search(coefficients, l, r);
    cout << fixed << setprecision(6) << x << endl;
    return 0;
}

Problem - G2 - Codeforces

这道交互算法题目要求找出一个缺失的刻度值 ( x ) (满足 ( 2 < x < 999 ))。对长度为 ( y ) 的物体进行测量时,尺子会根据 ( y ) 和 ( x ) 的关系给出不同的测量结果:

  • 如果 ( y < x ),则尺子正确测量为 ( y )。
  • 如果 ( y >= x ),则尺子错误测量为 ( y + 1 )。

你可以通过查询形如 ? a b 的指令,测量 ( a * b ) 矩形的面积,返回的面积是根据秘密尺子的测量结果计算的。题目中说明,通过最多 7 次查询找到 ( x ) 的值,查询返回的面积会受到 ( x ) 的影响。

每个测试用例独立,输入的第一行是测试用例的数量 ( t )( ( 1 <= t <= 1000 ))。正确输出找到的 ( x ) 值格式为 ! x,输出错误或超过查询次数将导致程序失败。

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

int query(int a, int b){
    cout << "? " << a << " " << b << endl;
    int res;   
    cin >> res;
    return res;
}

int main(){
    int task;
    cin >> task;
    while (task--){
        int l = 1, r = 999;
        while (l + 1 < r){
            int midl = l + (r - l) / 3;
            int midr = l + (r - l) * 2 / 3;
            int res = query(midl, midr);
            if (res == midl * midr){
                l = midr;
            }
            else if (res == midl * (midr + 1)){
                l = midl;
                r = midr;
            }
            else{
                // assert(res != (midl + 1) * (midr + 1));
                r = midl;
            }
        }
        cout << "! " << r << endl;
    }
    return 0;
}
相关推荐
lu_rong_qq22 分钟前
决策树 DecisionTreeClassifier() 模型参数介绍
算法·决策树·机器学习
LNTON羚通6 小时前
摄像机视频分析软件下载LiteAIServer视频智能分析平台玩手机打电话检测算法技术的实现
算法·目标检测·音视频·监控·视频监控
哭泣的眼泪4088 小时前
解析粗糙度仪在工业制造及材料科学和建筑工程领域的重要性
python·算法·django·virtualenv·pygame
Microsoft Word8 小时前
c++基础语法
开发语言·c++·算法
天才在此9 小时前
汽车加油行驶问题-动态规划算法(已在洛谷AC)
算法·动态规划
莫叫石榴姐10 小时前
数据科学与SQL:组距分组分析 | 区间分布问题
大数据·人工智能·sql·深度学习·算法·机器学习·数据挖掘
茶猫_10 小时前
力扣面试题 - 25 二进制数转字符串
c语言·算法·leetcode·职场和发展
肥猪猪爸13 小时前
使用卡尔曼滤波器估计pybullet中的机器人位置
数据结构·人工智能·python·算法·机器人·卡尔曼滤波·pybullet
readmancynn13 小时前
二分基本实现
数据结构·算法
萝卜兽编程13 小时前
优先级队列
c++·算法