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

算法竞赛中的三分(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;
}
相关推荐
未来之窗软件服务5 小时前
自己写算法(九)网页数字动画函数——东方仙盟化神期
前端·javascript·算法·仙盟创梦ide·东方仙盟·东方仙盟算法
豐儀麟阁贵5 小时前
基本数据类型
java·算法
乐迪信息7 小时前
乐迪信息:基于AI算法的煤矿作业人员安全规范智能监测与预警系统
大数据·人工智能·算法·安全·视觉检测·推荐算法
hsjkdhs8 小时前
C++之多层继承、多源继承、菱形继承
开发语言·c++·算法
立志成为大牛的小牛8 小时前
数据结构——十七、线索二叉树找前驱与后继(王道408)
数据结构·笔记·学习·程序人生·考研·算法
星空下的曙光8 小时前
Node.js crypto模块所有 API 详解 + 常用 API + 使用场景
算法·node.js·哈希算法
StarPrayers.10 小时前
旅行商问题(TSP)(2)(heuristics.py)(TSP 的两种贪心启发式算法实现)
前端·人工智能·python·算法·pycharm·启发式算法
爱吃橘的橘猫10 小时前
嵌入式系统与嵌入式 C 语言(2)
c语言·算法·嵌入式
2351610 小时前
【LeetCode】146. LRU 缓存
java·后端·算法·leetcode·链表·缓存·职场和发展
weixin_3077791311 小时前
使用Python高效读取ZIP压缩文件中的UTF-8 JSON数据到Pandas和PySpark DataFrame
开发语言·python·算法·自动化·json