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

2 篇文章 0 订阅

疯牛

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

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

#include<stdio.h>
#include<algorithm>
#define N 100005
int 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;
		else
			y=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;
}


 


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值