【算法刷题-第5题】蜂巢-Python

问题描述

蜂巢由六边形拼接而成,定义蜂巢中的方向:0表示正西方向,1表示西偏北60°,2表示东偏北60°,3表示正东,4表示东偏南60°,5表示西偏南60°。

对于给定的一点O,以O为原点定义坐标系,如果一个点A由O点先向d方向走p步再向(d + 2) mod 6方向(d的顺时针120°向)走q步到达,则这个点的坐标定义为(d, p, q)。在蜂窝中,一个点的坐标可能有多种。 图给出了点B(0, 5, 3)和点C(2, 3, 2)的示意。 问:给定点(d1, p1, q1)和点(d2, p2, q2),请问他们之间最少走多少步可以到达?

输入格式

输入一行包含 6 个整数d1,p1,q1,d2,p2,q2表示两个点的坐标, 相邻两个整 数之间使用一个空格分隔。

输出格式

输出一行包含一个整数表示两点之间最少走多少步可以到达。

样例输入

输入

0 5 3 2 3 2

输出

7

题解

1. 本题属于构造类型的题,比较难一点。

2. 我们可以尝试转换一下模型,无非就是求两个点之前的最短距离,但是走的步数需要按照他的来

3. 我们先将蜂巢转换为坐标的形式,这个地方不好想:

4. 我们以一个半长为1,这样避免分数,通过这样的图,我们很清楚知道了我们要求两个点的距离

5. 首先我们应该先将我们输入的值转换为这坐标轴上面的坐标,也就是通过题意可以得知,我们是通过d来定义方向的

6. 于是按照他的数字提前写两个列表,来表示每次向某个方位移动一步的坐标变化:

redx = [-2,-1,1,2,1,-1]
redy = [0,1,1,0,-1,-1]

7. 然后我们将我们的dpq转换为坐标值:

def run(d,p,x,y):
  x += redx[d] *p
  y += redy[d] *p
  return x,y
x1,y1 = run(d1,p1,x1,y1)
x1,y1 = run((d1+2) % 6,q1,x1,y1)

x2,y2 = run(d2,p2,x2,y2)
x2,y2 = run((d2+2) % 6,q2,x2,y2)

整体来看,其实就移动了两步,所以可以定义一个函数,一个表示方向,一个表示步数

8. 找到坐标之后,我们就可以很清楚知道我们要求什么了,不过是两点的距离罢了,最短的无非就是平着走,然后再斜着走。

9. 于是咣咣写了下面代码,但是很遗憾只过了75%的样例

d1,p1,q1,d2,p2,q2 = map(int,input().split())
x1 = 0
y1 = 0
x2 = 0
y2 = 0
redx = [-2,-1,1,2,1,-1]
redy = [0,1,1,0,-1,-1]
def run(d,p,x,y):
  x += redx[d] *p
  y += redy[d] *p
  return x,y
x1,y1 = run(d1,p1,x1,y1)
x1,y1 = run((d1+2) % 6,q1,x1,y1)

x2,y2 = run(d2,p2,x2,y2)
x2,y2 = run((d2+2) % 6,q2,x2,y2)

dx = abs(x1-x2)
dy = abs(y1-y2)
print((dx+dy)//2)   # 这里//2的原因是,我们刚开始定义的一步其实坐标上面走了2格

10. 于是继续寻找另外的可能性

如果是这种情况的话,那么你两个直边相加//2的值是比直接走斜边要大的

11. 所以还有一种情况就是直接通过斜边来走,那么如何判断是否是直接在一条斜边上面呢?

12.

现在来看这张图,不难发现,如果你的dx>dy的话,也就是说,两个点之间的的横边大于竖直的边的话,那么这个你的斜边是不能连成一条线的,因此就得出了最后的代码:

代码

d1,p1,q1,d2,p2,q2 = map(int,input().split())
x1 = 0
y1 = 0
x2 = 0
y2 = 0
redx = [-2,-1,1,2,1,-1]
redy = [0,1,1,0,-1,-1]
def run(d,p,x,y):
  x += redx[d] *p
  y += redy[d] *p
  return x,y

# 求最后两个点的坐标
x1,y1 = run(d1,p1,x1,y1)
x1,y1 = run((d1+2) % 6,q1,x1,y1)

x2,y2 = run(d2,p2,x2,y2)
x2,y2 = run((d2+2) % 6,q2,x2,y2)

dx = abs(x1-x2)
dy = abs(y1-y2)
if dx > dy:   # 判断边长
  print((dx+dy)//2)
else:
  print(dy)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jiaoxingk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值