POJ3258—River Hopscotch—二分法求the largest mimmun

Description

Every year the cows hold an event featuring a peculiar version of hopscotch that involves carefully jumping from rock to rock in a river. The excitement takes place on a long, straight river with a rock at the start and another rock at the end, L units away from the start (1 ≤ L ≤ 1,000,000,000). Along the river between the starting and ending rocks, N (0 ≤ N ≤ 50,000) more rocks appear, each at an integral distance Di from the start (0 < Di < L).

To play the game, each cow in turn starts at the starting rock and tries to reach the finish at the ending rock, jumping only from rock to rock. Of course, less agile cows never make it to the final rock, ending up instead in the river.

Farmer John is proud of his cows and watches this event each year. But as time goes by, he tires of watching the timid cows of the other farmers limp across the short distances between rocks placed too closely together. He plans to remove several rocks in order to increase the shortest distance a cow will have to jump to reach the end. He knows he cannot remove the starting and ending rocks, but he calculates that he has enough resources to remove up torocks (0 ≤ M ≤ N).

FJ wants to know exactly how much he can increase the shortest distance *before* he starts removing the rocks. Help Farmer John determine the greatest possible shortest distance a cow has to jump after removing the optimal set of M rocks.

Input

Line 1: Three space-separated integers:  LN, and  M
Lines 2..  N+1: Each line contains a single integer indicating how far some rock is away from the starting rock. No two rocks share the same position.

Output

Line 1: A single integer that is the maximum of the shortest distance a cow has to jump after removing  M rocks

Sample Input

25 5 2
2
14
11
21
17

Sample Output

4

Hint

Before removing any rocks, the shortest jump was a jump of 2 from 0 (the start) to 2. After removing the rocks at 2 and 14, the shortest required jump is a jump of 4 (from 17 to 21 or from 21 to 25).

题意::给一组数共N个大小在0~L之间,求当去掉其中M个后,剩下数差的最小值。(本题要点,要包含 0 点,和  L 点)。

思路::先对N+2个数进行排序,最小值必然由相邻两个数相减得到。

(1)假设最小的差为mid,if(a[ cur ] - a[last] < mid)就把cur点去掉,如果去掉的个数大于M说明mid太大,否则就太小。

(2)去掉L个就剩下N+2-M个(包含了0和L)然后通过N+2-M-1次循环(因为如果有 k 个点,必然可以产生k-1个差),如果用到了L还不能满足,就说明mid太大,否则太小。

对于mid,我们通过二分法,定义l(left),r(right),使mid = (l+r)/2;通过进行比较,更新l,或者r。

更新原则(1)::if(去掉的点>M){r = mid;} else {l = mid;} 在(r>l+1)的情况下一直循环

更新原则(2)::if(用到 L 仍不能满足循环){r = mid;} else {l = mid;} 在(r>l+1)的情况下一直循环

代码(1)::

#include <iostream>
#include <sstream>
#include <ios>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <vector>
#include <string>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <climits>
#include <cctype>
using namespace std;
#define XINF INT_MAX
#define INF 0x3FFFFFFF
#define MP(X,Y) make_pair(X,Y)
#define PB(X) push_back(X)
#define REP(X,N) for(int X=0;X<N;X++)
#define REP2(X,L,R) for(int X=L;X<=R;X++)
#define DEP(X,R,L) for(int X=R;X>=L;X--)
#define CLR(A,X) memset(A,X,sizeof(A))
#define IT iterator
typedef long long ll;
typedef pair<int,int> PII;
typedef vector<PII> VII;
typedef vector<int> VI;
//const int MAXN = 10010;
//#define INF 0x3FFFFFFF

int a[50005];
int L,N,M;
bool ok(int mid)
{
	int last = 0,cur,tot = 0;//tot用来记录删除点的个数
	while(a[last]<L){       
		cur = last + 1;
		while(tot<=M+1){
			if(a[cur] - a[last] < mid){//此时要删除cur
				tot++;cur++;    
            }
			else break;
        }
			last = cur;
		if(tot>M) return false;//删除点多余M返回false,进行r = mid
    }
	return true;
}
int main()
{
	while(cin>>L>>N>>M){
		a[0] = 0;
		REP2(i,1,N)
			cin>>a[i];
		a[N+1] = L;
		int l = 0,r = L;
		int mid;
		sort(a,a+N+2);
		while(l<r-1){
			mid = (l+r)/2;
			if(ok(mid))
                l = mid;
			else r = mid;
		}
		if(l == L-1)
            l++;
		cout<<l<<endl;

	}
}
代码(2)::

#include <iostream>
#include <sstream>
#include <ios>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <vector>
#include <string>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <climits>
#include <cctype>
using namespace std;
#define XINF INT_MAX
#define INF 0x3FFFFFFF
#define MP(X,Y) make_pair(X,Y)
#define PB(X) push_back(X)
#define REP(X,N) for(int X=0;X<N;X++)
#define REP2(X,L,R) for(int X=L;X<=R;X++)
#define DEP(X,R,L) for(int X=R;X>=L;X--)
#define CLR(A,X) memset(A,X,sizeof(A))
#define IT iterator
typedef long long ll;
typedef pair<int,int> PII;
typedef vector<PII> VII;
typedef vector<int> VI;
//const int MAXN = 10010;
//#define INF 0x3FFFFFFF
/************************************************
*********************头文件**********************
************************************************/
int a[50005];
int L,N,M;
bool ok(int mid) {
    int last = 0;
    for (int i = 1; i < N+2-M; ++i) {//循环N+M-1次
        int cur = last + 1;
        while (a[cur] - a[last] < mid && cur < N+2) cur ++;//在这里cur会逐渐累加
        if (cur == N+2) return false;//出现a中最后一个元素,没有满足循环
        last = cur;
    }
    return true;//没有出现过最后一个元素
}
int main()
{
	while(cin>>L>>N>>M){
		a[0] = 0;
		REP2(i,1,N)
			cin>>a[i];
		a[N+1] = L;
		int l = 0,r = L;
		int mid;
		sort(a,a+N+2);//排序
		while(l<r-1){
			mid = (l+r)/2;
			if(ok(mid))
                l = mid;
			else r = mid;
		}
		if(l == L-1)
            l++;
		cout<<l<<endl;
	}
	return 0;
}


你可能感兴趣的:(二分法,poj,最大最小值)