1. 程式人生 > >列舉演算法之最大值

列舉演算法之最大值

題目描述

有一條河,河中間有一些石頭,已知石頭的數量和相鄰兩塊石頭之間的距離。現在可以移除一些石頭,問最多移除m塊石頭後(首尾兩塊石頭不可以移除),相鄰兩塊石頭之間的距離的最小值最大是多少。

輸入資料

第一行輸入兩個數字,n(2<=n<=1000)為石頭的個數,m(0<=m<=n-2)為可移除的石頭數目 隨後n-1個數字,表示順序和相鄰兩塊石頭的距離d(d<=1000)

輸出資料

輸出最小距離的最大值

樣例輸入

4 1
1 2 3

樣例輸出

3

 解題:

 列舉演算法,二分法。

求滿足條件fun()的最大值。可轉化為任意兩個求相鄰石頭間距離不小於d。

#include<cstdio>
#include<algorithm>
using namespace std;

int a[50001]={0},l,n,m,i;
bool fun(int m);

int main()
{
    scanf("%d%d",&n,&m);

        int left=0,right=l,mid,ans;
        for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
        sort(a,a+(n+1));
        while(right>=left)
        {
            mid=(left+right)/2;//mid表示最小的距離!
            if(fun(mid))
			{
            	left=mid+1;
            	ans=mid;
			}
			else
			right=mid-1;
        }
        printf("%d\n",ans);

}

bool fun(int mid)
{
	int start=0,x=0;//用start表示每次落腳點的座標,每落一次地更新一次start
	for(i=1;i<=n;i++)
	{
		if(a[i]-start<mid)
		x++;//x表示去掉的石頭數,如果mid大於要跳的距離,就跳過當前這個石頭,此時x++ ,並且不落地
		else
		start=a[i];//此時落地!
	}
	if(l-start<mid)//判斷最後一跳跳的距離要是小於mid的話那是不可以的
	return false;
	if(x>m)//要是x>m就說明最小距離mid太大啦
	return false;
	return true;
}