HDU 1030 Delta-wave

Delta-wave

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 8362    Accepted Submission(s): 3321


Problem 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
 

Source

總的來說就是找規律的問題,就是要由給出的序號找出這個三角形位於哪一行,哪一列(列有兩個,從左上到右下,從右上到左下),然後就是純粹的數學公式推導問題了,參考了別人的推導方法,具體如下:

在此座標系中,每個方格有兩個方向(橫向、縱向,即x,y方向)

那麼在此題中,不難看出每個三角形有三個方向(x,y,z)

X方向    


Y方向    


Z方向   


有了這些基礎之後,我們需要求解的就是在某點在各個方向上面的位置

例如:點n在三個方向的座標爲:

X=(int)sqrt(n-1)+1;

Y= (n - (X-1)*(X-1)+1)/2;

Z= (X*X - n)/2+1;

下面就是我個人對以上得出的公式的推導過程:

首先,X表示點n所在位置從上到下爲第X層,Y表示點n所在位置從左上到右下第Y層,Z表示點n所在位置從右上到左下第Z層。

觀察每一行的點,不難發現規律:

1.每一行最後一個數都是該行的平方值。

2.對於求某一點左上到右下是第幾層,等於該點的值減去所在的上一行最後一個數之後除以2,再加上1(爲什麼要除以2和加1呢?下面再細說)。

3.對於求某一點右上到左下是第幾層,等於該點所在行最後一個數減去該點的值之後加上1,再除以2(爲什麼要除以2和加1呢?下面再細說)。

解釋:

除了第一行外,對其他任意一行上的一點,無論該點左上到右下或從右上到左下,總有一個與它同在一個水平方向上(即同行)並與它相鄰的點屬於同一層次,即左上到右下或從右上到左下這兩個方向上有兩個水平方向相鄰的數是在同一層上,因此求一點在這兩個方向是第幾層都要除以2。加1主要是由該點的位置及以上條件所決定的,這樣確保所求位置方向座標準確。

#include<iostream>
#include<cmath>
using namespace std;
int calculate_x(int n)//從上到下數第x層
{
		return (int)sqrt(n-1)+1;//   x=(int)sqrt(n-1)+1
}
int calculate_y(int n,int x)//從左上到右下第y層
{
	return (n-(x-1)*(x-1)+1)/2;//第x層最左端的數爲(x-1)^2+1 , 最右端的數爲x^2
}
int calculate_z(int n,int x)//從右上到左下第z層
{
	return (x*x-n)/2+1;
}
int main()
{
	int m,n;
	while(cin>>m>>n)
	{
		int x1,x2,y1,y2,z1,z2,s;
		x1=calculate_x(n);
		y1=calculate_y(n,x1);
		z1=calculate_z(n,x1);
		x2=calculate_x(m);
		y2=calculate_y(m,x2);
		z2=calculate_z(m,x2);
		s=abs(x1-x2)+abs(y1-y2)+abs(z1-z2);
		cout<<s<<endl;
	}
	return 0;
} 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章