3月2日 二分答案(跳石头)

#include <iostream>
using namespace std;
using ll=long long;
const int N=1e6+9;
int a[N],L,n,m;
int check(int mid)
{
  int res=0,lst=0;
  for(int i=1;i<=n;i++)
  {
    if(a[i]-a[lst]<mid)
    {
      res++;
      continue;
    }
    lst=i;
  }
  if(L-a[lst]<mid)return m+1;
  return res;

}
int main()
{
  ios::sync_with_stdio(0),cin.tie(0);
  cin>>L>>n>>m;
  for(int i=1;i<=n;++i)cin>>a[i];
  ll l=0,r=1e9+5;
  while(l+1!=r)
 {
  ll mid=(l+r)/2;
  if(check(mid)<=m)l=mid;
  else r=mid;
}
  cout<<l<<endl;
  return 0;
}

这段代码是一种传统的算法问题,看起来像是装载问题(Load Balancing)或者类似问题的一种解法。其使用二分搜索算法来快速查找最优解。

变量说明:

  • L:一个整数,表示可用距离或长度的总量。
  • n:岛屿的数量。
  • m:要删除的石头数量。
  • a[N]:具体位置数组。

函数说明:

  • check(int mid) 函数以一个整数 mid 作为参数,返回受限于距离至少为 mid 的条件下需要移除的石头数量。

以下是代码逐行分析:

  1. 设置常规输入/输出流提升速度:
ios::sync_with_stdio(0),cin.tie(0);

  1. 读入总长度L、岛屿n和最大可移除石头数m,并读入每个岛屿之间的距离到数组a中:
cin>>L>>n>>m;
for(int i=1;i<=n;++i)cin>>a[i];

  1. 初始化二分搜索边界,得到可能的最小值l和最大值r:
ll l=0,r=1e9+5;

  1. 使用二分搜索来查找合适答案。检查是否能够在要求将任意两个相邻石块间隔距离至少为mid时,满足移除不超过m个石块的条件:
while(l+1!=r)
{
    ll mid=(l+r)/2;
    if(check(mid)<=m)l=mid;
    else r=mid;
}

  1. 输出答案:
cout<<l<<endl;

此外,check函数里有如下逻辑:

  • 迭代每个岛屿位置,如果当前位置与上一个未被移除的位置之差小于mid,则必须移除当前位置上的石头。
  • 如果末尾剩余部分小于mid也无法构成所需序列,则返回比允许的最多可移除数还大1(即返回 m+1),表示这种情况下不能只移除m个石头达到目标。

简而言之,代码实现了一个算法来找出将给定数组修改成任何连续两项差都至少为某个值,并且只能通过删除不超过固定数量元素达成目标状态所需要设置的这个“差”的最大可能值。

下面是 check 函数的代码逐行分析:

int check(int mid)
{
    int res=0,lst=0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]-a[lst]<mid)
        {
            res++;
            continue;
        }
        lst=i;
    }
    if(L-a[lst]<mid)return m+1;
    return res;
}

  1. 定义函数并初始化变量:

    • int check(int mid): 定义函数,接受一个整数 mid 作为参数。
    • int res = 0: 初始化移除的石头计数为 0。
    • int lst = 0: 记录上一个没有被移除的岛屿的索引。
  2. 循环遍历所有岛屿位置:

    for(int i=1; i<=n; i++)
    
  3. 如果相邻两个岛屿间距离小于 mid

    if(a[i] - a[lst] < mid)
    
  4. 增加移除岛屿的计数,并继续遍历下一个岛屿(使用 continue 跳过剩余循环体):

      {
          res++;
          continue;
      }
    
  5. 如果当前岛屿和上一次记录的岛屿之间距离不小于 mid,更新lst为当前索引值,这表示这个岛不需要移除:

      lst = i;
    
  6. 循环结束后,判断最后一个没有被移除的岛到最终位置L之间的距离是否也满足至少是 mid:

    if(L - a[lst] < mid) return m + 1;
    
  7. 最后返回必须移除的石头数量。如果最后一段距离不满足要求, 返回比允许值大1, 表示当前中间值无法满足只删除m块石头达成题目要求:

    return res;
    

在循环中每次检查两个连续未被移除的点之间是否满足最小距离约束。如果某两点之间距离太近(即小于给定的mid),则需要将效果较差的那块石头标记为已移除(实际操作是增加了res而没有直接修改数组)。函数返回总共需标记移除多少块石头才能保持每两块石头之间至少有指定的最小距离。如果任意时刻res超过了m,则说明此时给定的mid过大,在二分答案中应减小它以适配条件。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值