poj2456- Aggressive crows poj3258 - River Hopscotch 二分+贪心--最大化最小值+整数防死循环

poj 2456 Aggressive crows

此题核心在于二分搜索牛之间的距离,然后贪心地放牛作为判断是否满足条件的依据。

贪心:在满足两牛之间距离不小于d的情况下,如何尽可能多放牛?(关键,剔除了很多情况)

贪心之前往往要排序。

二分:二分搜索找出d,方便判断。

①注意整数二分的写法,有些写法有可能会陷入死循环

②关于最大化最小值和最小化最大值问题,到底取left还是right?

分解题意。

看二分写法,我的写法一般二分取left。刚开始被最大值最小化搞晕了,其实二分已经包含把最小值最大化的过程。


#include<iostream>

#include<algorithm>
#include<stdio.h>
using namespace std;


int X[100005];
int N,M;

bool Judge(int d)
{
int cur=0;
int i=cur+1;
int sum=1;
while(i<N&&cur<N)//还能被找到, 贪心下每头牛只要确定前面的位置,至于它放后面的位置就不是最优情况。
{
//cout<<"!"<<endl;
if(X[i]-d>=X[cur])//这里严格上应该是>号
{
cur=i;
i=cur+1;
sum++;
//cout<<d<<"de"<<cur<<"he"<<i<<"hewei"<<sum<<endl; 
}
else
i++; 
}
//if(sum==M)cout<<"yes"<<endl;
if(sum>=M)                //前面取点时候虽然头数相等,但不一定取到mid,而且要最大化最小值的话,所以要往大的搜
return true;
//cout<<"yes";
    return false;
}
int main()
{
int l=0;
int r=1000000000;
int mid;
cin>>N>>M;
for(int i=0;i<N;i++)
{
scanf("%d",&X[i]);//10^5的输入一定要用scanf!!!不然超时 
}
sort(X,X+N);//贪心之前常常要排序

for(int i=0;i<35;i++)//控制二分次数,很好用
// while(l<r)//死循环 
    //while(l<r-1)//l、r整数适用 
{
mid=(l+r)/2;
//cout<<mid<<endl;
if(Judge(mid))
l=mid;
else
r=mid;
}
cout<<l<<endl;

}


poj3258  River Hopscotch


与上题区别仅在于多了一个终点,虽然终点不可删,但其实贪心的过程完全一样。

#include <iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
int L,M,N;
int a[5000010];


bool Judge(int d)
{
int cur=0;
int i=1;
int sum=1;
while(i<=N+1&&cur<=N+1)
{
if(a[i]-a[cur]>=d)//这里严格意义是大于号
{
cur=i;
i=cur+1;
sum++;
}
else
i++;

}
//cur=N;
    // i=N-1;
//int sum2=1;
//while(i>0&&cur>0)
//{
// if(a[cur]-a[i]>=d)
// {
// cur=i;
// i=cur-1;
// sum2++;
// }
// else
// i--;
// } 


// cout<<d<<" de"<<sum<<endl; 
if(sum>=N-M+2)//等于号也要往大的找,同上
return true;
else
return false;
}


int main()
{
cin>>L>>N>>M;
a[0]=0;
for(int i=1;i<=N;i++)
{
scanf("%d",&a[i]);
}
a[N+1]=L;
sort(a,a+N+2); 
int l=0;
int r=1000000001;
int mid;
for(int i=0;i<100;i++)
{
mid=(l+r)/2;
if(Judge(mid))
l=mid;
else
r=mid;
}
cout<<l<<endl;
}

猜你喜欢

转载自blog.csdn.net/zjyang12345/article/details/80245580