POJ 3258 最小值最大化 二分搜索

题意:牛要到河对岸,在与河岸垂直的一条线上,河中有N块石头,给定河岸宽度L,以及每一块石头离牛所在河岸的距离,

          现在去掉M块石头,要求去掉M块石头后,剩下的石头之间以及石头与河岸的最小距离的最大值。

首先去理解题意,去除一些石头之后,使得跳跃的最短距离是最大的,这个跳跃的距离一定是一个值而且一定小于总距离,同时我们可以知道的是,如果移除某几块石头,以某一最短距离跳跃都满足的话,小于这个最短距离的话一定都满足,大于这个最短距离便不一定,所以二分搜索的好处在于可以精准地通过之前的判断对下一次的范围进行锁定,进行判断,确保获得最大的最短距离。进行判断的时候我们可以通过不断地顺序试探,如果跳跃距离小于要求的最短距离,则需要将移除的石头加一。并且之后的距离就是将这块石头移除之后的距离,注意这里就有一个顺序。从前往后。我在做本题时主要对终点的那段距离抱有疑惑,其实终点那段虽然终点不能移除,但只要要移除的石头数小于等于n,就可以通过移除之前的石头实现。如果要移除n+1块石头那显然也不符合m<=n的要求。

难点两个:

1,二分搜索最短距离值

2,顺序的通过该值去判断删去一些石头是否满足(实际删去的石头数量和需要删除的数量),算距离时还要注意起点的变化。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define MAXN 50005
 6 using namespace std;
 7 int num[MAXN];
 8 int l,n,m;
 9 bool solve(int dist){
10     int ans=0,j=0;
11     for(int i = 1;i<= n+1 ; i++){
12         if(num[i] - num[j]<dist){
13             ans++;
14         }
15         else
16         {
17             j = i;
18         }
19     }
20     if(ans > m)
21         return false;
22     else
23         return true;
24 }
25 int main(){
26     int i;
27     scanf("%d%d%d",&l,&n,&m);
28     num[0]=0;
29     for(i = 1; i <= n ; i++){
30         scanf("%d",&num[i]);
31     }
32     sort(num,num+n+1);
33     num[n+1] = l;
34     int left = 0,right = l;
35     int mid = 0 ;
36     int val = l;
37     while(left<=right){
38         mid = left + (right - left) / 2;
39         if(solve(mid)){
40             val = mid ;
41             left = mid + 1;
42         }
43         else
44             right = mid - 1;
45     }
46     cout<<val<<endl;
47     return 0;
48 }

 

转载于:https://www.cnblogs.com/fancy-itlife/p/4719780.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值