zoukankan      html  css  js  c++  java
  • 7.10 二分跳石头游戏(二分答案)

    今天为大家讲解一道我刚刚做的二分题目,重点在于理解以及考虑特殊情况。

    题目描述  

      每逢过年,奶牛们玩跳石头游戏。这个游戏在一条笔直的河上进行。河上两个石头被作为起点和终点,

    它们之间的距离为L(1≤L≤10)。还有N(0≤N≤50000)个 石头放置在这两个石头之间,每个石头距离起点都有

    一个独一无二的整数距离D(0<D<L)。

      游戏进行的时候,奶牛们从起点开始,依次跳到每一个相邻的石头上,最终到达终点。约翰对自己的

    奶牛很有信心。他每年都到场观看这奶牛们的游戏。今年,约翰终于不耐这个游戏的无聊,打算做一些手

    脚,好让别的农夫的奶牛出丑。他打算除掉M(0≤M≤N)个石头,使任意两个石头间的最短距离变得尽量大。

    这样,别人家的奶牛就很有可能失蹄了。

      请计算,采取最佳方案移除石头之后,最短距离是多少。注意,约翰不能移除起点和终点的石头。

    输入说明


    第1行输入L,N,M。接下来N行,每行一个整数表示一个石头的位置


    输出说明


    移除石头后的最短距离


    输入样例

    25 5 2

    2

    14

    11

    21 

    17

    输出样例:

    4

    样例说明:

      移除之前,最短距离在位置2的石头和起点之间;移除位置2和14两个石头后,最短距离变成17和21或

    21和25之间的4

    题解代码:

    #include<iostream>
    #include<string>
    #include<algorithm>
    using namespace std;
    int l,n,m,a[50011];
    bool check(int mid){//函数用于测试最短距离为mid时需要除去的石头数量
     int last=0,tot=0;
     for(int i=1;i<=n;i++){
      if(a[i]-a[last]<mid){
       tot++;
       if(tot>m){
        return false;//说明当前mid偏大
       }
      }
      else{
       last=i;
      }
     }
     return true;//当前tot<=m,mid偏小
    }
    int main(){
    // freopen("past_river.in","r",stdin);
     scanf("%d%d%d",&l,&n,&m);
     for(int i=1;i<=n;i++){
      scanf("%d",&a[i]);
     }
     
     a[++n]=l;
     sort(a,a+n+1);
     /*
     for(int i=1;i<=n;i++){
      printf("%d ",a[i]);
     }printf("\n");
     */
     int l1=0,ans;
     int r=l;
     
     while(l1<=r){
      int mid=(l1+r)/2;
     // printf("%d\n",mid);
      if(check(mid)){//mid偏小
       ans=mid;
       l1=mid+1;
      }
      else{
       r=mid-1;//mid偏大
      }
     }
     printf("%d\n",ans);
     
     return 0;
    }
     
    题解思路:
      设置a[]数组来依次表示各个石头与起点间的距离,a[n+1]表示终点与起点的距离, l设为河的长度,将数组与起点距离按由近到远进行排序。
    1.设置一个bool型的check函数,判断最短距离为mid时应移去多少块石头。
    函数中,设移除数量为tot,tot>m时说明mid过大,返回false;tot<=m时,说明mid偏小,返回true
     

    2.最短距离最长为l,用二分查找,while(l<=r)l,r来查找最短距离,取平均数mid,用函数check来判断mid的 值:

      1.返回true,说明mid小于或等于正确答案,将ans赋值为mid,l=mid-1;

      2.返回false,除去的石头过多,说明mid大于正确答案

    注:在这里需要注意一种情况,很多同学习惯于使用while(l<r),l=mid,r=mid-1,但在这道题中,会陷入死循环

    最终结果输出ans即为正确答案

  • 相关阅读:
    scrapy.FormRequest与FormRequest.from_response 的区别
    可迭代对象和生成器
    css选择器
    xlwt写入excel时候的合并单元格
    html form提交的几种方式
    Python decorator 拦截器
    python manage.py makemigrations & migrate
    asianux4.5 环境, 本地yum源,局域网yum源的配置
    mysql基本操作
    sqlite-mysql migrate
  • 原文地址:https://www.cnblogs.com/cxs070998/p/11163969.html
Copyright © 2011-2022 走看看