【 NOIP 2015 】【 Day2 T1 】【 跳石头 】【 二分 】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/violinlove/article/details/81636550

luogu传送门

虽然说看到了最小值最大,想到了二分,然鹅,没有想到怎么二分(肤浅的觉得复杂度 会炸 ,太弱了 -_- )

重点:体会这次二分,虽然简单,但是竟没有想出来

下次想不到的时候,从需要回答的问题入手::输出(最大的)最小值,二分 最短距离,判断此距离 能否 通过 至多 移动 m 个石头 而 存在,因为要每一段距离 都满足 这个最小值 ,所以看到不满足的就移动石头。

代码比较好些,但是,想不到!!谨记,多思考:10mins,OK?

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define inf 0x7f7f7f7f
#define LL long long

using namespace std;

inline int wread(){
    char c(getchar ());int wans(0),flag(1);
    while (c<'0' || c>'9'){if (c=='-') flag=-1;c=getchar ();}
    while (c>='0' && c<='9'){wans=wans*10+c-'0'; c=getchar ();}
    return wans*=flag;
}

int sum,n,m;

int a[50006];

int l=inf,r;

bool jud (int dis){
	int num(0);
	int la(0);
	for (int i(1);i<=n+1;++i){
		if (a[i]-la<dis)	num++;
		else la=a[i];
	}
	
	if (num<=m)	return true;
	return false;
}

int pr;

int main(){
	sum=wread();n=wread();m=wread();
	for (int i(1);i<=n;++i)	a[i]=wread(),l=min(l,a[i]-a[i-1]);
	l=min(l,sum-a[n]);
	a[n+1]=sum;
	r=sum;
	pr=l;
	while (l<r){
		int mid ((l+r)/2);
		if ( jud(mid) )	pr=max(pr,mid),l=mid+1;
		else r=mid;		
	}
	printf("%d\n",pr); 
	return 0;
}

暴力算法: dfs  期望得分:20   实际得分:20  不要乱加剪枝 !!!

乱搞算法:dfs + 假贪心 ( 或直接假贪心 )  期望得分:20+未知  实际得分:60

此算法 无法每次都得到最优解,但是接近最优解

复杂度 接近 n^{2}  会  T 一个点,WA   3  个点,得分:(数据+人品)60

算法:求出 每一块石头间 的距离差,每次选择 最小的的一个区间,比较左右两个区间,选择更小的哪一个,合并 -> (表示拿掉两个区间之间的石头) 【 我第一遍做的时候写的算法 】【 虽然没什么知识上的意义,但是对于应试 来说,很有实际意义 】【 不能写出正解的情况下 便可以 拿完所有暴力分 + 乱搞 (包括猜极端、易错、不好想的数据 以及 偏小概率错误解法) 】

猜你喜欢

转载自blog.csdn.net/violinlove/article/details/81636550