第十三届蓝桥杯省赛 JAVA A组 - 蜂巢

✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:蓝桥杯题解集合
📝原题地址:蜂巢
📣专栏定位:为想参加蓝桥杯的小伙伴整理常考算法题解,祝大家都能取得理想成绩!
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

问题描述

蜂巢由六边形拼接而成,定义蜂巢中的方向: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),请问他们之间最少走多少步可以到达?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yFqAwd0c-1674207746588)(AcWing 蓝桥杯辅导.assets/19_3a72026935-QQ截图20220916100647.png)]

输入格式

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

输出格式

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

数据范围

对于 25% 的评测用例,p1,p2≤103
对于 50% 的评测用例,p1,p2≤105
对于 75% 的评测用例,p1,p2≤107
对于所有评测用例,0≤d1,d2≤5,0≤q1<p1≤109,0≤q2<p2≤109

输入样例:
0 5 3 2 3 2
输出样例:
7
思路

这道题从图上来看其实并不难,假设我要从 B 到 C 找到最短路径,实际上就只能从右下走,但是难就难在这题没有给定坐标系,坐标系需要我们自己分析构建。

我们以 O 点为原点,以每个蜂巢的中心点作为每一处坐标,构建坐标系:

观察上图可知,如果直接用曼哈顿距离公式来计算两点之间的距离是不正确的,但可以发现如下规律(假设两点之间的横坐标之差的绝对值为 d x = ∣ x 1 − x 2 ∣ dx=|x1-x2| dx=x1x2∣,纵坐标之差的绝对值为 d y = ∣ y 1 − y 2 ∣ dy=|y1-y2| dy=y1y2∣):

  • 如果 dx 大于 dy,则两点之间的距离为 ( d x + d y ) / 2 (dx+dy)/2 (dx+dy)/2
  • 如果 dx 小于 dy,则两点之间的距离为 d y dy dy
  • 如果 dx 等于 dy,上面的两种公式都能得到正确答案

举个例子,假设从 (-1,1) 到 (1,-1),其 dxdy 分别为 2 和 3。故 dy 大于 dx ,则最少要走 3 步。

再举个例子,假设从 (-1,1) 到 (2,0),其 dxdy 分别为 3 和 1。故 dx 大于 dy,则最少要走 (1+3)/2=2 步。

代码
#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
LL d1, p1, q1, d2, p2, q2;
LL dx[] = { -2,-1,1,2,1,-1 }, dy[] = { 0,1,1,0,-1,-1 };

void walk(LL d, LL s, LL& x, LL& y)
{
    x += dx[d] * s;
    y += dy[d] * s;
}

int main()
{
    cin >> d1 >> p1 >> q1 >> d2 >> p2 >> q2;

    //计算第一个坐标
    LL x1 = 0, y1 = 0;
    walk(d1, p1, x1, y1);
    walk((d1 + 2) % 6, q1, x1, y1);

    //计算第二个坐标
    LL x2 = 0, y2 = 0;
    walk(d2, p2, x2, y2);
    walk((d2 + 2) % 6, q2, x2, y2);

    //计算dx和dy
    LL dx = abs(x1 - x2), dy = abs(y1 - y2);

    //根据计算结果输出对应答案
    if (dx >= dy)  cout << (dx + dy) / 2 << endl;
    else cout << dy << endl;

    return 0;
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值