Description
A triangle field is numbered with successive integers in the way shown on the picture below.
The traveller needs to go from the cell with number M to the cell with number N. The traveller is able to enter the cell through cell edges only, he can not travel from cell to cell through vertices. The number of edges the traveller passes makes the length of the traveller‘s route.
Write the program to determine the length of the shortest route connecting cells with numbers N and M.
Input
Input contains two integer numbers M and N in the range from 1 to 1000000000 separated with space(s).
Output
Output should contain the length of the shortest route.
Sample Input
6 12
Sample Output
3
题目大意就是有数字a走到数字b的最小步数,走的时候只能跨线走,不能跨点走。
首先我想到一个错误的想法,就是不妨设a<b,a先走斜线到b的同一层,然后再往b走。
但是发现一些例子不满足。
也就是这种折型走法不行。
但是通过上面的走法发现,可以走一个平行四边形的走法,就是a先走到c,c再走到b。
不过这次的不同是a是走斜线到c,c再走斜线到b。
首先第一次的走法发现了,从a走到b同一层的最短路径就是斜线。例如(1->3->2->6->5...),一路走过的都是最短走到的。
那么很容易证明第二种走法就是最短路了。
然后就是数学计算了,先根据每层的数字数目是个等差数列,然后根据不等式判断出a和b的层数,然后通过解方程得出c的位置,然后就是计算了,需要对情况中步数需要+1的情况特殊处理一下。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <set> #include <queue> #include <vector> #define LL long long using namespace std; int n, m; int getLow(int x) { int i = sqrt(x); while ((i-1)*(i-1) >= x) i--; while (i*i < x) i++; return i; } void work() { int kn, km, kp, in, im, ip, ans; kn = getLow(n); km = getLow(m); in = n-(kn-1)*(kn-1); im = m-(km-1)*(km-1); if (km == kn) ans = abs(im-in); else if (in > im || 2*kn-in > 2*km-im) { ans = 2*(km-kn)-in%2+abs(in+in%2-im); in = 2*kn-in; im = 2*km-im; ans = min(ans, 2*(km-kn)-in%2+abs(in+in%2-im)); } else { ip = in+in%2; im = 2*km-im; kp = (ip+im+im%2)/2; ans = 2*(kp-kn)-in%2+abs(in+in%2-ip); ip = 2*kp-ip; ans += 2*(km-kp)-ip%2+abs(ip+ip%2-im); } printf("%d\n", ans); } int main() { //freopen("test.in", "r", stdin); while (scanf("%d%d", &n, &m) != EOF) { if (n > m) swap(n, m); work(); } return 0; }