hdu1030一道有规律的数学题,
仔细分析就可以得出结果,嘿嘿。。
作者:贾钰(Jeick Jia) CS@SCU
时间:2011-4-25
6 12
3
题目的意思很明确,从一个格子到另一个格子最短需要穿过几次三角形的边。现在Jeick找出了它的规律,请开始听Jeick絮叨吧。
首先,每一层(lay)的数据是由特点的,最后面一个数字 n ,有关系 n = pow(lay,2)+1,对于第一个数字呢t,有关系 t =pow(lay-1,2).OK,根据这个关系呢,我们就可以求出任意一个数在这个塔中的层数:
lay = (int)ceil(sqrt((double)n));
其中sqrt不用介绍吧,ceil函数功能是向上取整,有C++math库提供。
然后呢,我们再观察另一个规律left,left表示给出的数字在塔中 左上→右下 斜行中的第几行,例如1,3,2,6,5,……就是在一斜行,我们称之为left行,计算left:
left = (n-lay_first)/2+1
其中lay_first表示n所在层得第一个数字。
有left规律,那么就得有right规律嘛,right规律的第一同理left,
right = (lay_last-n)/2+1;
其中 lay_last表示n所在层得最后一个数字。
ok,我们的定义结束,现在就找这些定义之间的关系。
设有起始位置在 front ,重点位置在 back
从图中我们可以看出,从front出发至back穿过的三角形边只有三种情况对吧,水平边,左边,右边,同时也会发现:
水平边等于 lay_front,lay_back的差值 △lay
左边等于 right_front, right_back的差值 △right
右边等于 left_front,left_back的差值 △left
于是结果就显而易见了:result = △lay+△right+△left
代码就很简单了,下面是我的代码:
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int front,back;
while(cin>>front>>back)
{
int lay_front = (int)ceil(sqrt((double)front));
int lay_back = (int)ceil(sqrt((double)back));
int right_front = (front-(lay_front-1)*(lay_front-1)-1)/2+1;
int right_back = (back-(lay_back-1)*(lay_back-1)-1)/2+1;
int left_front = (lay_front*lay_front-front)/2+1;
int left_back = (lay_back*lay_back-back)/2+1;
cout<<abs(lay_front-lay_back)+abs(right_front- right_back)+abs(left_front-left_back)<<endl;
}
return 0;
}