河中跳房子(二分

每年奶牛們都要舉辦各種特殊版本的跳房子比賽,包括在河裏從一塊岩石跳到另一塊岩石。這項激動人心的活動在一條長長的筆直河道中進行,在起點和距離起點 L 遠的終點各有一塊岩石 (1 ≤ L ≤ 10^9)。在起點和終點之間,有 N 塊岩石 (0 ≤ N ≤ 50000),每塊岩石與起點的距離分別爲 Di (0 < Di < L)。

在比賽過程中,奶牛輪流從起點出發,嘗試到達終點,每一步只能從一塊岩石跳到另一塊岩石。當然,實力不濟的奶牛無法抵達終點,在河中間就退出比賽了。

農夫約翰爲他的奶牛們感到自豪並且年年都觀看了這項比賽。但隨着時間的推移,看着其他農夫的膽小奶牛們在相距很近的岩石之間緩慢前行,他感到非常厭煩。他計劃移走一些岩石,使得從起點到終點的過程中,最短的跳躍距離最長,跳到終點的距離不計入。他可以移走除起點和終點外的至多 M 塊岩石 (0 ≤ M ≤ N)。

請幫助農夫約翰確定:移走這些岩石後,最短跳躍距離的最大值是多少?

輸入
第 1 行包含以單個空格分隔的三個整數 L, N, M。

第 2 到 N + 1 行,每行一個整數,表示每個岩石與起點的距離。不會有兩個岩石出現在同一個位置。

輸出
輸出一個整數,即最短跳躍距離的最大值。

示例輸入
25 5 2
2
14
11
21
17
示例輸出
4
提示
在移除位於 2 和 14 的兩塊岩石之後,最短跳躍距離達到了最大值 4 (從 17 到 21,或從 21 到 25)。

解題思路
1)起點和終點也是石頭,它們之間有N個石頭
2)移除的時候只能移除N個石頭中的M個,起點和終點的石頭是不能移除的
3)奶牛是一塊石頭一塊石頭的跳的!!
4)a[i]是每個岩石與起點的距離(我老是忘了
我們是用二分法去推求最長可能的最短跳躍距離
假設最大的最短跳躍距離是d 那麼與a[i]的距離小於d的都要被移除 暫定最開始的d=mid=(l+r)/2 即全程的一半
然後以這個標準進行岩石的篩選
以起點爲基點,如果從基點到第一塊岩石(先sort一遍排個序)的距離小於mid,就把第一塊移除掉 統計被移除石頭的ans++,然後就是第二塊,如果從基點跳到第二塊石頭的距離還小於d,那就把第二塊也給移除掉,nas++
就這麼找下去,直到找到一個超過mid的,把它作爲基點,再繼續遍歷下去,逐漸移除石頭
就這樣篩選完之後 剩下的沒被移除的石頭中,它們之間的距離一定是大於mid的 ,然後再來判斷下ans與m的大小,
ans<=m 說明當前移除的石頭還沒有達到上限 也就是在篩選過程中的mid值過小啦 那就讓l往右移動下,因爲要找最優解嘛
ans>m 說明移動的石頭超過上限了 也就是mid值過大 那就讓l往左移動下

代碼如下

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5;
int a[maxn];
int n,m,h;
int judge(int mid)
{
	int i;
	int ans=0,k=0;
	for(i=1;i<=n+1;i++)
	{
		if(a[i]-k<mid)
		  ans++;
		else
		  k=a[i];
	}
	if(ans>m)
	  return 0;
	else
	  return 1;
}
int main()
{
	int i;
	int l,r;
	int ans;
	cin>>h>>n>>m;
	for(i=1;i<=n;i++)
	  cin>>a[i];
	a[n+1]=h;//終點的那塊石頭
	sort(a+1,a+n+2);
	l=1;
	r=h;
	while(l<=r)
	{
		int mid=(l+r)/2;
		if(judge(mid))//去掉的石頭<=m個 
		{
			ans=mid;
			l=mid+1;
		}
		else
		{
			r=mid-1;
		}
	}
	cout<<ans<<endl;
	return 0;
}

有的人直接輸出的mid 然後不對。。我們需要時刻記錄mid的 因爲在一直尋找最優解,mid也一直在變 如果在mid符合條件的時候不記錄下來 它可能會變成一個不符合的 最後循環終止 輸出的也是一個不符合的

啊啊啊終於寫完了 太噁心心了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章