二分优化---无限逼近求解

摘要:

通过对一个问题两种解法分析,揭示了二分逼近求解的精妙之处

 

问题描述如下:

给定N( 1 <= N <= 100000) 个数,求往N个中数取C(2 <=C< N)个数,使C个数之间两两之差的最小值在同类情况下是最大的。

 

sample:

 N = 5, C = 3;

N个数为:  1,2,8,4,9

解的情况为: 1,8,4; 最小值为 3。

其他同类情况可以为1,2,9 or 1,2,4 etc,但是其最小值均为1,不是最佳解。

 

第一种解法:

对 N个数进行子集树回溯,然后对每种情况挑出最小值,然后再和maxnum比较,最后出结果。但是这种解法不好地方在于N的个数太大,深搜会出现runtime error。

 

第二种解法:

在0----num[n-1]之间取一值, 假设其为最佳解,和N个数的两两值差进行比较,再统计有多少个值差在假设值之上,若统计值大于等于C则把假设值降低,再进行判断,反之则提高数值.在提高和降低假设值的过程需要用到二分查找.所需要的时间为nlogn,远远高效于回溯的2^n

 

相关代码如下:

 

//代码粘得比较不可观;
#include <stdio.h>

int a[100000];
int n,m;

bool find(int v)
{
  int pre=a[0],c=0;
   
 for(int i=1;i<n;i++)
 {
      if(a[i]-pre>=v)
     {
           c++;
           pre=a[i];  
     }   
  }  

  if(c>=m)
  return true;
 else
  return false;
}

int cmp(const void *x,const void *y)
{
      return *(int *)x-*(int *)y;  
}

int main()
{
    //freopen("in.txt","r",stdin);
    scanf("%d%d",&n,&m);
    m--;
   
 for(int i=0;i<n;i++)
 {
      scanf("%d",&a[i]);
 }

    qsort(a,n,sizeof(a[0]),cmp);  
   
    int left=0,right=a[n-1],mid;
   
 while(left<=right)
 {
      mid=(left+right)/2;
   
      if(find(mid))
          left=mid+1;
      else
          right=mid-1;  
  }  
   
      printf("%d/n",left-1);
  return 0;
}

 相关的二分法练习如下:

http://acm.pku.edu.cn/JudgeOnline/problem?id=3388
http://acm.pku.edu.cn/JudgeOnline/problem?id=2456
http://acm.zju.edu.cn/show_problem.php?pid=2002

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值