路标设置(整数域上二分)

本文解析了洛谷P3853题目中关于路标放置的算法实现,通过二分查找确定最大间距以确保任意两路标间距离不超过规定值,并详细阐述了解决方案。

题目:

见https://www.luogu.com.cn/problem/P3853

思路:

之前做这题一直WA,甚至一个样例都过不,还是思路出现了问题.
正确的思路:在区间[0,L]上进行二分,每对一个mid值就判断路标数是否足够,能使得所有相邻路标间的距离都<=mid,如果不能那么l=mid+1,否则r=mid,有一个细节就是路标间距如果能整除mid,那么需要添加的路标数就应该是间距÷mid-1

代码:

#include<iostream>
#include<climits>
#include<cmath>
using namespace std;
const int n=100010;
int points[n];
int L,N,K;
int max_num=INT_MIN;
bool check(int mid)
{
    int cnt=0;
    for(int i=1;i<=N-1;i++)
    {
        int distance=points[i+1]-points[i];
        if(distance>mid)
        {
            cnt+=distance/mid;
            if(distance%mid==0)
            cnt--;
        }
    }
    if(cnt<=K)
    return 1;
    else
    return 0;
}
int main()
{
    cin>>L>>N>>K;
    for(int i=1;i<=N;i++)
    cin>>points[i];
    int l=0,r=L+1;
    while(l<r)
    {
        int mid=l+r>>1;
        if(check(mid)) r=mid;
        else
        l=mid+1;
    }
    cout<<l<<endl;
    return 0;
}
### TJOI2007 路标设置 算法题解 此问题的核心在于通过二分答案的方法来寻找最优解,从而最小化公路的“空旷指数”。以下是详细的解析: #### 1. 问题描述 给定一条长度为 $L$ 的公路以及若干已有路标的坐标位置,目标是在这条公路上新增一些路标,使任意两个相邻路标之间的最大间距尽可能小。最终输出这一最大间距的最小值。 输入数据包括: - 公路总长度 $L$ - 已有路标的数量 $n$ - 每个路标的坐标位置列表 $a_1, a_2, \dots, a_n$ 注意:起点和终点必定存在路标[^1]。 --- #### 2. 解决方案概述 该问题可以通过 **二分查找** 来求解。具体来说,我们尝试找到一个合适的间隔值 $d$,使得在满足条件的情况下能够覆盖整个公路范围内的所有点。为了验证某个候选值是否可行,我们需要模拟放置新的路标并检查其合理性。 主要步骤如下: - 定义二分上下界:初始时设定左边界为可能的最小间隙(即 1),右边界为当前最大的已知差距。 - 对于每一个中间值 $mid$,执行可行性检测函数 `check(mid)` 判断是否存在一种方式布置额外标志物以达成不超过指定阈值的要求。 - 如果可以,则继续缩小上限;否则扩大下限直至收敛到最佳结果为止。 这种方法的时间复杂度接近线性时间级别 O(log(max_diff)*N),其中 max_diff 表示原始数组中的最远两点差额[^4]。 --- #### 3. 实现细节与伪代码 下面提供了一个基于上述逻辑的具体实现框架 (C++): ```cpp #include <bits/stdc++.h> using namespace std; // Function to check feasibility of placing signs with maximum distance 'dist' bool canPlace(vector<int> &positions, int L, int dist){ int lastPos = positions[0]; // Start from the first position for(int i=1;i<positions.size();i++){ if(positions[i]-lastPos > dist){ // If gap exceeds allowed limit return false; } lastPos = positions[i]; } if(L-lastPos > dist) { // Check end condition return false; } return true; } int main(){ ios::sync_with_stdio(false); cin.tie(0); int n,L; cin>>n>>L; vector<int> pos(n); for(auto &p : pos)cin>>p; sort(pos.begin(),pos.end()); int l=1,r=L,res=-1; while(l<=r){ int mid=(l+r)/2; if(canPlace(pos,L,mid)){ res=mid;r=mid-1;// Try smaller values as we want minimal possible answer. }else{ l=mid+1; // Need larger spacing between consecutive markers. } } cout<<res<<"\n"; } ``` --- #### 4. 关键点解释 - **排序操作**: 将所有的现有标记按照从小到大的顺序排列起来以便后续处理更加方便快捷[^3]。 - **canPlace 函数的作用**: 此辅助功能用来评估特定的最大允许距离是否足以完成任务。它遍历现有的每一对连续节点,并确保它们之间不会出现超过预定义界限的情况发生[^5]。 - **调整策略的选择依据**: 当前测试的距离参数成功实现了既定目的之后,应该进一步探索是否有更优的结果可用;反之则需放宽约束条件重新试探其他可能性[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值