虽然说看到了最小值最大,想到了二分,然鹅,没有想到怎么二分(肤浅的觉得复杂度 会炸 ,太弱了 -_- )
重点:体会这次二分,虽然简单,但是竟没有想出来
下次想不到的时候,从需要回答的问题入手::输出(最大的)最小值,二分 最短距离,判断此距离 能否 通过 至多 移动 个石头 而 存在,因为要每一段距离 都满足 这个最小值 ,所以看到不满足的就移动石头。
代码比较好些,但是,想不到!!谨记,多思考:,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;
}
暴力算法: 期望得分: 实际得分: 不要乱加剪枝 !!!
乱搞算法: + 假贪心 ( 或直接假贪心 ) 期望得分:未知 实际得分:
此算法 无法每次都得到最优解,但是接近最优解
复杂度 接近 会 一个点, 个点,得分:(数据+人品)
算法:求出 每一块石头间 的距离差,每次选择 最小的的一个区间,比较左右两个区间,选择更小的哪一个,合并 -> (表示拿掉两个区间之间的石头) 【 我第一遍做的时候写的算法 】【 虽然没什么知识上的意义,但是对于应试 来说,很有实际意义 】【 不能写出正解的情况下 便可以 拿完所有暴力分 + 乱搞 (包括猜极端、易错、不好想的数据 以及 偏小概率错误解法) 】