石头移动问题
问题及分析来源:https://www.icourse163.org/course/NJTU-1003359012
1 问题描述
有一条河,河中间有一些石头,石头的数量以及相邻两块石头之间的距离已知。现在可以移除一些石头,假设最多可以移除m块石头(注意:首尾两块石头不可以移除,且假定所有的石头都处于同一条直线),问最多移除m块石头后相邻两块石头之间的最小距离的最大值是多少?
输入:
多组输入( <=20组数据,读入以EOF结尾),每组第一行输入两个数字: n(2<=n<=1000)为石头的个数, m(0<=m<=n-2)为可移除的石头数目,随后n-1个正整数,表示顺序相邻两个石头的距离d(d<=1000)。
输出:
每组输出一行结果,表示最大值
2 初步分析
首先可能会想到贪心策略:
- 选择距离最近的两颗石子
- 再从两颗石子中选择距离相邻石子最近的
对于上图,首先确定1 2两颗石子,由于1不能动,因此选择2进行移除,则最终结果为3
然而,对于第二个图,若要求移除两颗石子。
运用之前确定的贪心策略,首先确定2 3两颗,然后选择第3颗移除;之后又选择第4颗移除,得到最终结果为3。
但是,若选择第2 4颗进行移除,最后得到的结果为5,因此贪心无效。
3 进行穷举
简单的构造循环很难列举出所有的情况,此时可以采用递归的办法进行枚举。
构造一个长度为n的数组,1表示移除,0表示保留
经过此代码,最终会形成高度为n-2的二叉树,每条从根到叶子节点的路径都代表一种情况,时间复杂度为O(2^n)
虽然这种方法能够解决问题,但是时间复杂度过大
4 二分枚举
我们可以逆向考虑问题,假设最终结果为d,即移除m个石头后,所有相邻石子的间距都大于等于d。
即:对任意的间距小于等于d的相邻石子,都不能存在,必须移除其中的一颗。
以下为验证d合法的算法:(dis[i]表示第i颗石子距离第一颗石子的距离)
选择d可以采用二分枚举的方式,我认为上界可设置为dis[n],代码中设置的是1000*1000+5
整个代码时间复杂度为O(nlogn)。