HDU1030 Delta-wave【详细解释】

1.问题简介:给你一个三角形里面是successive integer(连续的整数)。要求只能通过边来从一个元素访问另一个元素,求从点M到点N的最短路径(即从M开始最短通过几条边到达N)。

原文图像

2.问题分析:

为了更方便的分析,我画了一张图来看里面的结构,即只能通过边来访问。(发现这个图很美,有点像蜂巢的六边形,不断延续下去)。最开始我是想通过dijkstra最短路访问,最后发现构图是个问题,而且最短路需要O(n²),所以换别的思路。看了原来大神的思路,才明白一些。

 

1.刚开始的思路

 从3号到12号需要5个步骤,3种动作,只要求出3种动作每个有多少步,然后加起来即是最短步骤。

3.具体分析:

(参考博主https://www.cnblogs.com/ACMan/archive/2012/05/30/2526798.html

我们规定   :    计算从m点到n点的最短距离。cm 是m的行数cn 是n的行数

(如计算点6到点12,m为6,n为12,cm = 3,cn = 4)。

1.中间图
2.左划图
3.右划图

 

 

 

 

 

①。计算中间图2层之间差值:

cm = (int)ceil(sqrt(m));    /*ceil是math.h中的函数,代表(取上界)*/
cn = (int)ceil(sqrt(n));

②。计算左划图2层之间差值:

我们规定:         lm 是m左移层数ln 是n左移层数

lm = (int)ceil( (m-(cm-1)*(cm-1))/2.0 );
ln = (int)ceil( (n-(cn-1)*(cn-1))/2.0 );

③。计算右移之间差值:

我们规定:         rm 是m右移层数rn 是n右移层数

rm = (int)ceil( (cm*cm-m+1)/2.0 );
rn = (int)ceil( (cn*cn-n+1)/2.0 );

4.详细代码:

#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    int m,n,cm,cn,lm,ln,rm,rn;
    while(cin >> m >> n)
    {
        cm = (int)ceil(sqrt(m));
        cn = (int)ceil(sqrt(n));
        lm = (int)ceil( (m-(cm-1)*(cm-1))/2.0 );
        ln = (int)ceil( (n-(cn-1)*(cn-1))/2.0 );
        rm = (int)ceil( (cm*cm-m+1)/2.0 );
        rn = (int)ceil( (cn*cn-n+1)/2.0 );
        cout << (int)(fabs(cm-cn)+fabs(lm-ln)+fabs(rm-rn)) << endl;
    }
    return 0;
}

5.Note:

1.有些同学可能个别解是对的,个别是错的。没错我也遇到了,最后debug了一下,发现是把2改成2.0就对了。

比如1/2取上界是0,因为1/2赋值给int值是0,而1/2.0结果为float型,可以保存。

2.还有一个问题是:

①。ceil函数,他的原型是:(所以最后结果可以(int)一下子,使他结果为整数。)

double ceil( double x)
{
    return 大于等于x的整数。
}

②。floor函数,他的原型与ceil类似,返回的是小于等于x的最大的整数。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值