poj2456- Aggressive crows poj3258
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;
}