hdu 1030 求最短路径

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

总体思路是: 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;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值