poj 3258 River Hopscotch 题解
【题意】
牛要到河对岸,在与河岸垂直的一条线上,河中有N块石头,给定河岸宽度L,以及每一块石头离牛所在河岸的距离,
现在去掉M块石头,要求去掉M块石头后,剩下的石头之间以及石头与河岸的最小距离的最大值。
【解法】
用二分做,但是开始写了三个版本的二分,全都wa。
无赖看了别人的二分,还是不理解,为什么他们写的就能过。
反复思索后,终于明白了:关键在于题目求的是什么。
做题思想:二分所求的最小距离的最大值mid,记录可以去掉的石头块数cnt(注意:当相邻的石头的距离小于等于mid,就可以去掉),
若cnt > M,h = h - 1 (这里是比较难理解的,也是我纠结挺久的地方),此时,应当回过头来看一下题目求的是什么:
寻找一个长度mid,使得可以去掉M块石头,剩下的石头中,石头间的最小距离为mid。
但是cnt记录的是:相邻距离小于等于mid的块数,所以存在这样的一种情况 ---- cnt记录的所有石头中,
有很多块石头间的距离是等于mid,而距离小于mid的石头的块数是小于等于M的,此时,若将h的值减一,
那么h的值就变成一个小于题目所求的答案了。
举个例子就懂了:假设有9块石头,首尾的数都表示河岸。
石头的编号 1 2 3 4 5 6 7 8 9
石头到河岸的距离 0 4 5 7 9 12 16 19 23 26 28
相邻的距离 4 1 2 2 3 4 3 3 3 2
假设l = 1,h = 5, M = 4 则mid = 3, 此时去掉的石头的编号为:2,3,5,7,9 cnt = 5
按照程序,h = h - 1 = 4,此时mid = 2,去掉的石头的编号就为:2,4,9 cnt = 3(cnt<M了,
当然也有可能cnt == M,总之就是cnt > M不成立了)
也就是说,之后求得的cnt <= M恒成立, 即题目的答案不在 l 和 h 之间了(这点
之前是让我很费解的地方),更准确地说,答案就是执行这次h-1之前的h值。
若cnt <= M,则l = l + 1,讨论一下:若cnt < M,明显当前的mid小了,l = l + 1;若cnt == M,则去掉cnt块石头后,
剩下的石头的最小值必然是大于mid的,所以进行操作l = l + 1。
然后解决上面遇到的问题,因为h已经小于答案了,而答案就是h+1,之后继续二分cnt <= M恒成立,
l 不断自增,直到跳出循环,因为答案为h+1,我们返回 l 的值,那么while的判断条件就是 l <= h,
当 l 自增到 h + 1时就跳出循环,l == h + 1,正好就是答案。
写了这么多,就是分析了一下二分算法执行的过程,因为以前用的二分while判断条件都是 l < h,看样子以后做二分得多注意了,
稍不注意就会有很多致命的小bug,一定要将对 l 和 h 的操作以及 while的判断条件结合起来考虑,要对二分算法进行灵活的变化,
没有一成不变的模版,具体问题具体分析。
【代码】
/*
Problem:poj 3258
By:S.B.S.
/*
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstdlib>
#include<iomanip>
#include<cassert>
#include<climits>
#define maxn 10001
#define F(i,j,k) for(int i=j;i<=k;i++)
#define M(a,b) memset(a,b,sizeof(a))
#define FF(i,j,k) for(int i=j;i>=k;i--)
#define inf 0x7fffffff
#define p 23333333333333333
using namespace std;
int l,n,m;
int d[50005];
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline int run(int le,int h,int k)
{
int mid,last,cnt;
while(le<=h)
{
mid=(le+h)>>1;
last=cnt=0;
F(i,1,n+1){
if(mid>=d[i]-d[last]) cnt++;
else last=i;
}
if(cnt>k) h=mid-1;
else le=mid+1;
}
return le;
}
bool cmp(int a,int b)
{
return a<b;
}
int main()
{
std::ios::sync_with_stdio(false);//cout<<setiosflags(ios::fixed)<<setprecision(1)<<y;
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout);
cin>>l>>n>>m;
d[0]=0;
d[n+1]=l;
F(i,1,n){
cin>>d[i];
}
sort(d+1,d+1+n,cmp);
cout<<run(0,l,m)<<endl;
return 0;
}
poj 3258
poj 3258 River Hopscotch 题解的更多相关文章
- 二分搜索 POJ 3258 River Hopscotch
题目传送门 /* 二分:搜索距离,判断时距离小于d的石头拿掉 */ #include <cstdio> #include <algorithm> #include <cs ...
- POJ 3258 River Hopscotch
River Hopscotch Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 11031 Accepted: 4737 ...
- POJ 3258 River Hopscotch (binarysearch)
River Hopscotch Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 5193 Accepted: 2260 Descr ...
- POJ 3258 River Hopscotch(二分答案)
River Hopscotch Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 21939 Accepted: 9081 Desc ...
- [ACM] POJ 3258 River Hopscotch (二分,最大化最小值)
River Hopscotch Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 6697 Accepted: 2893 D ...
- POJ 3258 River Hopscotch(二分法搜索)
Description Every year the cows hold an event featuring a peculiar version of hopscotch that involve ...
- poj 3258 River Hopscotch(二分+贪心)
题目:http://poj.org/problem?id=3258 题意: 一条河长度为 L,河的起点(Start)和终点(End)分别有2块石头,S到E的距离就是L. 河中有n块石头,每块石头到S都 ...
- POJ 3258 River Hopscotch 二分枚举
题目:http://poj.org/problem?id=3258 又A一道,睡觉去了.. #include <stdio.h> #include <algorithm> ]; ...
- poj 3258 River Hopscotch(二分搜索之最大化最小值)
Description Every year the cows hold an ≤ L ≤ ,,,). Along the river between the starting and ending ...
随机推荐
- 【PAT】1012. 数字分类 (20)
1012. 数字分类 (20) 给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字: A1 = 能被5整除的数字中所有偶数的和: A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算 ...
- 5 Linux网络编程基础API
5.1 socket地址API 大端字节序(网络序):高位在低址,低位在高址 小端字节序(主机序):低位在低址,高位在高址 判断,利用联合的特性: #include <iostream> ...
- s12-day04-work01 简单计算器功能实现
代码: #!/usr/local/env python3 ''' Author:@南非波波 Blog:http://www.cnblogs.com/songqingbo/ E-mail:qingbo. ...
- Centos7 Openldap主从配置
转载 https://blog.csdn.net/htvxjl02/article/details/80336788 Centos7 Openldap主从配置 2018年05月16日 15:09:57 ...
- laravel windows安装(composer)
1.安装composer参考windows 安装tp5 composer方式 2.先配置好本地虚拟域名,在cmd里面切换到网站根目录 ... 3.安装成功之后,在浏览器输入已配置的虚拟域名我的是,la ...
- CodeForces 785B Anton and Classes
简单判断. 找第一类区间中$R$最大的,以及第二类区间中$L$最小的,判断距离. 找第二类区间中$R$最大的,以及第一类区间中$L$最小的,判断距离. 两种情况取个最大值即可. #include &l ...
- 深度学习基础系列(一)| 一文看懂用kersa构建模型的各层含义(掌握输出尺寸和可训练参数数量的计算方法)
我们在学习成熟网络模型时,如VGG.Inception.Resnet等,往往面临的第一个问题便是这些模型的各层参数是如何设置的呢?另外,我们如果要设计自己的网路模型时,又该如何设置各层参数呢?如果模型 ...
- c++源文件后缀名问题
VC里用cpp作后缀名, 在GCC里默认采用C.cc.cxx作为后缀名 .cpp, .h (VS file).cc, .h (GCC file) C中: 头文件后缀名: .h 源文件后缀名: .c ...
- 我的OI生涯 第一章
第一章 一入电竞深似海 我叫WZY,是TSYZ的一名学生. 2016年7月10日,我进了一个叫做oi的坑. 那时的我不知道什么叫竞赛,不知道什么叫编程,不知道什么是c++. 就记得前一天我特意去图 ...
- JZYZOJ1311 邮局设置问题 dp
易得每两个点之间建立邮局的最好位置为两点最中间的点,两点之间如果没有奇数个数的点则中间两个点都可以...(自己画一下图可以看出随着右边点的增大最佳点的增大非常平滑...强迫症一本满足) w[i][ ...