蜂窝小区最短距离实现 (极坐标+等差数列,十行代码搞定)

题目描述:由正六边形组成的蜂窝小区中,每个正六边形的编号如图所示。求任意2点间的距离。(规定最大编号不超过100000)

 

真的是Python十行代码搞定,估计C++也是十几行的代码。分析题目,提炼数学模型,再写代码。


这个题可以不用各种复杂的算法,从数学角度解决。用数学思维简化逻辑模型,而不是用计算机逻辑代替数学思维……
四大常用坐标系:笛卡尔直角坐标,极坐标,柱坐标,球坐标。这道题应该采用极坐标!加上等差数列!就够了~

firstValue, secondValue为给的2点,Python代码如下:

 1     n_fir = int(math.ceil((1+math.sqrt(1 + 4*(firstValue-1)/3))/2))
 2     n_sec = int(math.ceil((1+math.sqrt(1 + 4*(secondValue-1)/3))/2))
 3     if firstValue == 1:
 4         shortestPathLength = n_sec-1
 5     elif secondValue == 1:
 6         shortestPathLength = n_fir-1
 7     else:
 8         angle_fir = (n_fir*(n_fir-1)*3+1-firstValue)*2*math.pi/(6*(n_fir-1))
 9         angle_sec = (n_sec*(n_sec-1)*3+1-secondValue)*2*math.pi/(6*(n_sec-1))
10         shortestPathLength = round(math.sqrt((n_fir-1)**2+(n_sec-1)**2-2*(n_fir-1)*(n_sec-1)*math.cos(angle_fir-angle_sec)))
11     return int(shortestPathLength)

 

 

详细解释如下:

极坐标确定一个点,两点之间的距离公式  

图中可以用归纳法总结出等差数列:

圈号(等于极坐标轴长r-1)容量最小编号最大编号
11(用0代替)1(用0代替)1(用0代替)
26(6*1)27
312(6*2)819
418(6*3)2037
524(6*4)3861

 

 

 

 

 

 

 

把第一圈的容量假设为0,最小最大编号假设为0,就是等差数列。(说明我们可以对含有编号1的特殊处理,其他的编号可以一起处理)

数字1、2、3、...、N-1、N,的隐含条件是:1)数字是有秩序(index)的,2)数字的秩序数(index)恰好等于该秩序处数字的值。

等差数列通项公式、求和公式

这里初值 a1 = 0, 公差d = 6

那么,Sn = ((圈号*(圈号-1))/2)*d + 1;  (最后加1是因为我们把a1=0了,实际编号从1开始的,所以这里加上)

 

给定编号怎么算位于第几圈呢?

对求和公式整理得,n^2 -n -2*Sn/d = 0,把编号赋给Sn,解一元二次方程,因为△>0,所以有解:

 根据公式舍弃一个负根,剩下的一个正跟就是解n(一个小数),对n向上取整,就是该编号对应的圈号。

向上取整:把离散的圈号看成连续的,那么(2,3]区间是属于第3圈。

极坐标定位:(设圈号为n, 已知点p)

 = n-1

 = ((n*(n-1)/2)*d + 1 - p)*π*/(d*(n-1)); π = 3.14...(圆周率),意思就是(第n圈的最大编号-给定的编号)*(圆周率/该圈的容量)!

所以,给定两个点p1, p2,用求出距离,再四舍五入,就是任意2点间的距离!

四舍五入:连接任意两个蜂窝的中心,会发现连线是对称的。

最后,注意下,如果给定的2个点含有1,那么直接返回[另一个的圈号-1]

 

转载于:https://www.cnblogs.com/onduty/p/5709379.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值