贪心算法二分法枚举

来源:互联网 发布:校园网络诈骗小品剧本 编辑:程序博客网 时间:2024/06/07 01:01

贪心二分枚举

二分枚举是参数搜索的一个改善。

对于一个问题,如果它的答案具有单调性质(即如果i不可行,那么大于i的解都不可行,而小于i的解有可能可行),进而用二分的方法枚举答案,再判断答案是否可行,直到求到符合条件为止。

例如:问题的答案范围是1到w之间的一个整数,求最小解,那么我们设s=1,t=w,之后mid=(s+t)整除2。然后判断当解是mid的时候这个问题能不能解决,如果能解决则和最优解比较,并且范围缩小到s到mid-1之间(因为即使这个范围没有解,那么mid是最小解);如果不能解决问题,则最小解肯定比mid要大,则范围缩小到mid+1和t之间。如此反复知道s=t时判断完结束。

这时候那个记录最优解的变量一定记录的是能够达到的最优解。

简单来说就是假设一个答案,然后判断是否可行,并且不断缩小范围。

二分枚举答案的时间复杂度是O(log2 n),而判断时间是O(K)的话总的时间复杂度是O(Klog2 n)如果某个问题符合这个性质并且K比较小的话这个方法相当实用。

例题:nyoj疯牛

/*

题意:简单的说就是给你一段长度,在这一段中给出m个点,然后在这m个点中选出k个点,让这k个点之间相邻两个点的之间距离的最小值最大

思路:通过二分枚举这个最小值,然后通过贪心的思想找出满足要求的最大的这个最小值

解析:二分枚举 + 贪心

这道题用到了刘汝佳算法入门经典上贪心那一节讲的算法,用二分枚举满足条件的最大距离,依次做相应判断.本题不需要担心最后求出的距离不能适应题目中的隔间之间的距离,

因为二分枚举之后是按照贪心法判断的,如果当前距离满足要求,会继续增大枚举的距离,

一直到无法满足要求为止,即最后结果一定满足是隔间间的距离 .

*/

#include<stdio.h>

#include<stdlib.h>

int a[100050],n,c,i;

int cmp(const void*a,const void*b)

{

return*(int*)a-*(int*)b;

}

 

int judge(int mid)

{

int count=1,t=a[0];//count是指放了几头牛,从1开始。t用来表示当前的房间号  

for(i=1;i<n;i++)

{

if(a[i]-t>=mid)//判断两个隔间之间的距离

{

count++;

t=a[i];//修改t的值,即修改当前房间号,例如原来t=1,a[2]=4,若a[2]-t>=mid符合,那么t=4,然后算a[3]或者a[4]与t之间的距离。

if(count>=c)//可以放下c头牛

return 1;

}

}

return 0;

}

 

int binary()//二分搜索符合条件的最小距离的最大值  

{

int low=0,high=a[n-1]-a[0],mid;

//high代表排序后,两个相差最远的点的距离

while(low<=high)

{

mid=(low+high)/2;//mid即为最小房间号与最大房间号之间的距离

if(judge(mid))

low=mid+1;//所求距离>=mid,可以继续增大试探

else

high=mid-1;//所求距离<mid,所以必须减小来试探

}

return low-1;//由于在之前low距离+1,所以此时-1  

}

 

int main()

{

while(scanf("%d%d",&n,&c)!=EOF)

{

     for(i=0;i<n;i++)

     scanf("%d",&a[i]);

     qsort(a,n,sizeof(a[0]),cmp);

     printf("%d\n",binary());

}

return 0;

}

 什么是枚举

 

 

 

原创粉丝点击