| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
二分法,逼近最佳解。我们假设要求最小的区间是x,当前的条件下能否满足这个最小区间呢?我们知道,如果能满足最小区间x,那么x1<x的x1也都可以满足。所以求最大的x,一定在一个分界点,所有小于x的最小区间要求都可以满足,所有大于x的最小区间要求都不能满足,这样可以用二分法在解空间里面找到这个分界。
写一个C(x)函数,传入的x是最小区间的要求,判断能否满足这个要求。
使用二分法,如果mid能满足要求,那么临界点一定在mid-ub,否则临界点就在lb-mid。
/**
* 最大化最小值
*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#define MAX_N 50000
#define INF 9999999999
void solve(void);
bool C(unsigned long x);
unsigned long L,N,M;
//l 长度1-1,000,000,000
//N 石头数量
//M 可移除的石头数量
unsigned long D[MAX_N+100];
using namespace std;
int main(void)
{
cin>>L>>N>>M;
for(int i = 1; i <= N;i++)
{
scanf("%lu",D+i);
}
D[N+1] = L;
sort(D,D+N+2);
solve();
return 0;
}
void solve(void)
{
if(N==0&&M==0) cout<<L<<endl;
else
{
unsigned long ub=INF,lb=0;/*解区间,尽量让解更大*/
while(ub-lb>1)
{
unsigned long mid = (ub+lb)/2;
// printf("%lu,%lu,%lu\n",lb,ub,mid);
if(C(mid)) lb = mid;
else ub = mid;
}
cout<<lb;
}
}
/**
* 计算是否可以满足最低间隔是x的要求
*
* */
bool C(unsigned long x)
{
//这里的算法是这样的,计算出来能达到x间距所需的最少的移走石头数量,然后和M比较,如果<=M,就可以,否则据不可
//如何计算所需的最少移走石头数量呢?移走的石头最少,区间数量就越多,计算最多的区间数量即可。
//如何计算最多的区间数呢,从start开始,计算到下一个石头的距离,如果>=x,那么就表示这个区间可以保留,就保留住
//如果实在是不能保留这个区间,就找下一个石头,和下一个符合要求的石头组成一个区间
//只要能满足区间>x就保留这个区间,满足区间数量最多,移动石头最少
unsigned long st = 0,ed = 1,sum=0;//初始区间
while(ed<=(N+1))
{
if(D[ed]-D[st] >= x)
{
// printf("%lu 到 %lu 符合要求\n",D[st],D[ed]);
st = ed;
sum++;
}
ed++;
}
//现在得到的区间最多数目sum,这样就能求出来最少需要去掉几个石头
if( (N+1-sum) > M) return false;
return true;
}
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator