Jumping Jack
题面翻译
题目简述
从原点开始移动,目标为点 x x x 。第 n n n 次移动 n n n 个单位。每次皆可以向左、右两个方向跳跃,求到达 x x x 所需要的最少移动次数。
输入仅一行,一个整数 x x x ( − 1 0 9 ≤ x ≤ 1 0 9 ) (-10^9\leq x\leq 10^9) (−109≤x≤109) 。
输出到达 x x x 所需要的最少移动次数。
@Aw顿顿 感谢您提供的翻译
题目描述
Jack is working on his jumping skills recently. Currently he’s located at point zero of the number line. He would like to get to the point x x x . In order to train, he has decided that he’ll first jump by only one unit, and each subsequent jump will be exactly one longer than the previous one. He can go either left or right with each jump. He wonders how many jumps he needs to reach x x x .
输入格式
The input data consists of only one integer x x x ( − 1 0 9 < = x < = 1 0 9 -10^{9}<=x<=10^{9} −109<=x<=109 ).
输出格式
Output the minimal number of jumps that Jack requires to reach x x x .
样例 #1
样例输入 #1
2
样例输出 #1
3
样例 #2
样例输入 #2
6
样例输出 #2
3
样例 #3
样例输入 #3
0
样例输出 #3
0
思路
我们可以通过大量的画图可以知道,由根据对称性可以知道,你从0往-x跳跟从0往x跳时等效的,如果从原点开始一直跳能到终点那肯定是最优解。但当我们不能一直向右跳跳到终点的时候,我们这时候肯定得向左跳,为了保持最优解,我们可以在第一次即将要跳过终点的那个点开始往左跳,(也就是当y-x为奇数的时候,往回跳)。
总的来说:考虑第一次超过x的位置y,1到y-x的所有数一定是所有跳跃长度的子集。当y-x为偶数时,(y-x)/2一定为整数,且一定在向前跳跃长度的集合中,若将这一步改为向后跳跃,那么最终y-(y-x)/2-(y-x)/2=x,(其实本质上也就是:当当前和目标点 y-x为偶数,则 (y-x) / 2 的那一步向左跳,这样会少跳 y-x ,正好补在多跳的这一段。)即跳跃到x和跳跃到y的步数是相等的,只是改变了其中一步的方向;当y-x为奇数时,那么继续跳下去,直到y与x的差为偶数时结束。
粗体字参考。
具体的来说可以看:
代码
#include<iostream>
#include<algorithm>
#define int long long
using namespace std;
//我们直接就认为往右跳,他们之间的距离是奇数就跳
int n;
int ans=2e9;
//爆炸
// void dfs(int x,int tot){
// if(x==n){
// ans=min(ans,tot-1);
// return;
// }
// if(x>n||x<-n)return;
// dfs(x+tot,tot+1);
// dfs(x-tot,tot+1);
// }
signed main(){
cin>>n;
if(n<0)n=-n;//跳到正数和负数是等效的
// dfs(0,1);
int cnt=0,x=0;
while(x<n||(x-n)&1){
cnt++;
x+=cnt;
}
cout<<cnt;
return 0;
}