POJ-3258 River Hopscotch
2015-12-27 00:25
288 查看
题意 :牛要到河对岸,在与河岸垂直的一条线上,河中有N块石头,给定河岸宽度L,以及每一块石头离牛所在河岸的距离,
现在去掉M块石头,要求去掉M块石头后,剩下的石头之间以及石头与河岸的最小距离的最大值。
自己一直在纠结一个问题,为什么这个要用二分做。。。
然后当时想法是能不能找出一个贪心思路,能够直接找出最小值。。然后又想到既然贪心能够直接找出最小值。那么还要二分干嘛。。。。。
有没有贪心找出最小值的方法呢。。。没有。。因为从N个里面减去M个。。枚举绝对超时。。。
所以思维进入一个死胡同
然后看了题解。。
思路是这样的,根据最小距离的性质,加上最后还有N-M个点。进行判断,当最小距离为x时,找出相邻距离大于等于x的N-M个点。。。
这样思路就出来了。。。。
参考题解(致谢)
但是这个题解是有问题的。。。。虽然能AC,但是数据太弱。
比如
1000 5 3
200 400 550 800 810
输出是400
正确是200.。。。。
问题出在,比如有前K个点满足了。。后面剩余的点的距离k还要与最小距离x判断一下。。。k<X也是不行的。。。
问题又来了。。。那么这种贪心,似乎又出现了问题?(其实没问题)。。这样的话,不从前面往后面,从后面往前面行不行?。。细想一下就知道是不行的
代码:
慢慢对二分加贪心有理解了。。。ORZ
现在去掉M块石头,要求去掉M块石头后,剩下的石头之间以及石头与河岸的最小距离的最大值。
自己一直在纠结一个问题,为什么这个要用二分做。。。
然后当时想法是能不能找出一个贪心思路,能够直接找出最小值。。然后又想到既然贪心能够直接找出最小值。那么还要二分干嘛。。。。。
有没有贪心找出最小值的方法呢。。。没有。。因为从N个里面减去M个。。枚举绝对超时。。。
所以思维进入一个死胡同
然后看了题解。。
思路是这样的,根据最小距离的性质,加上最后还有N-M个点。进行判断,当最小距离为x时,找出相邻距离大于等于x的N-M个点。。。
这样思路就出来了。。。。
参考题解(致谢)
但是这个题解是有问题的。。。。虽然能AC,但是数据太弱。
比如
1000 5 3
200 400 550 800 810
输出是400
正确是200.。。。。
问题出在,比如有前K个点满足了。。后面剩余的点的距离k还要与最小距离x判断一下。。。k<X也是不行的。。。
问题又来了。。。那么这种贪心,似乎又出现了问题?(其实没问题)。。这样的话,不从前面往后面,从后面往前面行不行?。。细想一下就知道是不行的
代码:
#include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <queue> #include <stack> #include <functional> #include <set> #include<sstream> #include <cmath> using namespace std; #define pb push_back #define PB pop_back #define bk back() #define fs first #define se second #define INF 1e9+10 #define sq(x) (x)*(x) #define eps (1e-10) #define clr(x) memset((x),0,sizeof (x)) #define cp(a,b) memcpy((a),(b),sizeof (b)) typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> P; const int maxn=50100; int L,N,M; int rock[maxn]; bool c(int len) { int last=rock[0]; int cnt,num; num=0; for(int i=1;i<=N;i++) { if(rock[i]-last>=len) { last=rock[i]; num++; if(num==N-M) break; } } if(num<N-M||L-last<len) return false; return true; } int main() { cin>>L>>N>>M; for(int i=1;i<=N;i++) cin>>rock[i]; rock[N+1]=L; sort(rock,rock+N+1); int left,right,mid; left=0; right=INF; while(right-left>1) { mid=(right+left)>>1; if(c(mid)) left=mid; else right=mid; } cout<<left<<endl; return 0; }
慢慢对二分加贪心有理解了。。。ORZ
相关文章推荐
- 在Linux上批量处理邮件地址
- iOS 新建项目架构规范
- S5PV210环境搭建:arm-linux-gcc: 没有那个文件或目录
- Linux 常用命令汇总
- Centos修炼----->Centos7之Gcc安装
- linux虚拟机问题备忘
- django-nginx-uwsgi
- Linux C中struct tm结构与time_t相互转换
- 常用的系统性能监控工具
- 常用的几个监控脚本
- Open Live Writer (原Windows Live Writer开源)
- sysbench 测试IOPS
- sysbench 测试IOPS
- 13.Linux之软件安装
- Linux下MySQL C API简单示例
- 云服务器CentOS6.5搭建jdk7+tomcat7+mysql5.6环境
- 用kalinux 下面的mitmproxy 工具查看请求的时候会发现请求一个symcd.com
- Tomcat 环境配置
- Linux中程序包管理
- shell处理字符串的基本命令