总体思路是: m,n 两个数,始终保证,m是两者中较小的一个,这样就只有一种情况了, 从m,到达n, 只有往下走,到达n所在的行,并且,尽可能地离n较近,最后,计算到达n所在行时,m所在的位置,
这道题的思路是这样的, 首先找到每行中每个数到达下一行的规律。
然后
1 、
发现 奇数行,只有奇数可以直接一步到下一行,偶数行,只有偶数才能直接到下一行,并且对应的数字为 当前m 加上2 *m所在行。
2、
然后对不能直接到达下一行的数,发现,只要在同行先向左还是向右走一步,就可以变换到 条件1,直接到下一行。
关键就是在情况2 时决定是向左走,还是向右走。
判断标准就是, 找到m竖直对应的n所在的行的数字,设为期待n
desireN, 如果比n大,那就向左走,靠近n,否则向右走,同样靠近n
#include <iostream>
#include<cmath>
using namespace std;
int n,m;
int level(int x){
int i=(int)sqrt(x);
return i*i==x?i:i+1;
}
// calculate the vertical desired n for m in levle n
int desire(int m,int i,int j){
int incr=(j-i)*(i+j-1);
return m+incr;
}
int dist(int m,int n,int step){
if(m>n){
int t=m;
m=n;
n=t;
}
int lm=level(m);
int ln=level(n);
for(int i=lm;i<ln;i++){
if(i%2==0){
if(m%2==0){
m+=2*i;
step++;
}else{
// judge left or right
if(n>desire(m,i,ln)){
m+=1;
m+=2*i;
step+=2;
}else{
m-=1;
m+=2*i;
step+=2;
}
}
}else{
//
if(m%2==1){
m+=2*i;
step++;
}else{
// judge left or right
if(n>desire(m,i,ln)){
m+=1;
m+=2*i;
step+=2;
}else{
m-=1;
m+=2*i;
step+=2;
}
}
}
}
step+=(n-m)>0?(n-m):(m-n);
return step;
}
int main()
{
int result=0;
while(cin>>m>>n){
cout<<dist(m,n,0)<<endl;
}
return 0;
}

本文介绍了一种求解从数m到数n的最短路径的算法,通过分析数独矩阵的特性,找到了每行中数到达下一行的规律,并提出了一套完整的解决方案。该算法确保了始终处于较小数的状态,从而简化了问题。文章详细解释了如何判断行走方向以及计算最终距离。
4万+

被折叠的 条评论
为什么被折叠?



