nyoj 586 疯牛和nyoj 619 青蛙过桥 二分枚举+贪心

来源:互联网 发布:找货源软件 编辑:程序博客网 时间:2024/04/29 09:10

疯牛

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

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

#include<stdio.h>#include<algorithm>#define N 100005int a[N],n,m;bool greed(int k)  //判断当前找到的这个最小值{int s=a[0],i,count=0;for(i=1;i<n;i++){if(a[i]-s>=k){count++;s=a[i];}if(count>=m-1)  //当前找到的最小值偏小或恰好成立,可以再往偏大的地方找return true;}return false;    //找到当前的最小值偏大,需要再往偏小的地方找}void binary_search()  //通过二分找这个最小值{int x=0,y=a[n-1]-a[0],mid;while(x<=y){mid=(x+y)/2;if(greed(mid))  x=mid+1;elsey=mid-1;}printf("%d\n",x-1);  //当二分结束的时候,就可以找到这个最大的最小值}int main(){while(~scanf("%d%d",&n,&m)){for(int i=0;i<n;i++)scanf("%d",&a[i]);std::sort(a,a+n);binary_search();}return 0;}        

青蛙过桥

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

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

#include<iostream>#include<cstdio>#include<algorithm>using namespace std;int L,n,m,count1,p;int a[500005];bool greed(int x){    int s=0,i;    count1=0;    for(i=0;i<=n;i++)    {if(a[i]-s<=x) {           while(a[i]-s<=x&&i<=n) //贪心思想,找出当前最大值能包含的最多的相邻段                  i++;    s=a[--i];    count1++;}       }if(count1<=m)   //找到的当前最大值恰好或偏大,如果之前没有确定左端点,此处会出错(找到的最大值偏小的话会一直减小)        return true;    return false;}void binary_search(){    int l=p,r=a[n],mid;    while(l<=r)    {        mid=(l+r)/2;        if(greed(mid))            r=mid-1;        else         l=mid+1;    }    printf("%d\n",r+1);}int main(){    int i;    while(~scanf("%d%d%d",&L,&n,&m))    {p=0;        for(i=0;i<n;i++)           scanf("%d",&a[i]);           a[n]=L;           sort(a,a+n+1);   for(i=1;i<=n;i++)   if(p<a[i]-a[i-1])   p=a[i]-a[i-1]; //找到二分的左端点(很关键),此处wa了好几次           binary_search();    }    return 0;}


 


 

原创粉丝点击