问题描述
AB 实验同学每天都很苦恼如何可以更好地进行 AB 实验,每一步的流程很重要,我们目标为了缩短所需的步数。
我们假设每一步对应到每一个位置。从一个整数位置 x 走到另外一个整数位置 y,每一步的长度是正整数,每步的值等于上一步的值 -1, +0,+1。求 x 到 y 最少走几步。并且第一步必须是 1,最后一步必须是 1,从 x 到 y 最少需要多少步。
样例说明
- 整数位置
x为12,另外一个整数位置y为6,我们需要从x走到y,最小的步数为:1,2,2,1,所以我们需要走4步。 - 整数位置
x为34,另外一个整数位置y为45,我们需要从x走到y,最小的步数为:1,2,3,2,2,1,所以我们需要走6步。 - 整数位置
x为50,另外一个整数位置y为30,我们需要从x走到y,最小的步数为:1,2,3,4,4,3,2,1,所以我们需要走8步。
输入格式
输入包含 2 个整数 x,y。(0<=x<=y<2^31)
输出格式
对于每一组数据,输出一行,仅包含一个整数,从 x 到 y 所需最小步数。
输入样例
12 6
34 45
50 30
输出样例
4
6
8
想法
用易懂、自然的思路来解这道题。
我们观察到所有情况都是类似于1,2,3,...,k,...,3,2,1(像一个山峰,我们称其为k峰,k是山峰顶点的海拔,每个点的海拔相加得到一个值sum); 但是有些距离的答案并不完全就是一个k峰,有点像在一个k峰的基础上再加了几步。
用贪心的思想,我们知道,如果要步数最少,就要让k峰够大,所以最后答案其实是sum值最接近xy距离的一个k峰加上了小于等于k的n步(n>=0),不必纠结这几步加入到序列里面的位置,这几步见缝插针到序列里面即可。
所以答案由两部分组成,k峰的宽度(2*k-1)+插入的n步。
n步如何求呢?同样是用贪心的思想,尽可能一步走k个距离,最后不够k个距离再补一步。所以:xy距离-sum=a*k+b,即n=a或n=a+1(如果b不为0,再补一步)。
代码
int solution(int xPosition, int yPosition) {
//算距离
int dis = abs(xPosition - yPosition);
//特殊情况x和y重合
if(dis == 0) return 0;
//找到k值
int top = sqrt(dis);
//算要补大小为k的步子几步
int extra_top = (dis - top * top) / top;
//看最后还要不要补一步
int extra_normal;
if((dis - top * top) % top == 0)
extra_normal = 0;
else
extra_normal = 1;
//把走的所有步相加,返回
return 2 * top - 1 + extra_top + extra_normal;
}