【蓝桥杯】蜂巢问题-Java-最详细解

题目: 蓝桥杯2022年第十三届省赛真题-蜂巢

最近在准备蓝桥杯的算法训练, 这道题思路感觉还是很巧妙, 但是C语言网 和 CSDN上的解释都是十分的 粗略了, 注释很容易看不懂, 这篇文章算是抛砖引玉, 把自己的思考过程进行了分步复现, 总得来说 我感觉挺好理解的了~

问题:

蜂巢由大量的六边形拼接而成,定义蜂巢中的方向为: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)。在蜂窝中,一个点的坐标可能有多种。
Alt

下图给出了点 B(0, 5, 3) 和点 C(2, 3, 2) 的示意。

输入:

0 5 3 2 3 2

输出:

7

代码解释:

import java.util.Scanner;

/*
 * 定义蜂巢中的方向为:
 * 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)。
	在蜂窝中,一个点的坐标可能有多种
	
	给定点 (d1, p1, q1) 和点 (d2, p2, q2),
	请问他们之间最少走多少步可以到达?
 */
public class Hive {
	// 1. 将各个方向的单位移动距离 替换位 用新的十字坐标的单位移动距离
	
	// 新的直角坐标系 的单位刻度解释:
	// x 轴: 单位长度 为 1, 蜂巢的任何方向单位刻度都是1, 相同, 以此朝西运动1, 视为运用1个单位
	// y 轴: 单位长度 为 √3/2, 蜂巢的任何方向单位刻度都是1, 因此, 朝西偏北运动1时, y轴上运动√3/2, 但在新坐标体系下, 运动为1个单位
	// 数组的下标表示运动的方向, 数组的值表示在新直角坐标体系下运动的单位数
	public static double[] x = new double[] {-1,-0.5,0.5,1,0.5,-0.5};
	
	// 这里的y 单位长度为 √3/2, 1 表示一个单位长度
	public static double[] y = new double[] {0,1,1,0,-1,-1};
	
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int d1 = in.nextInt();
		int p1 = in.nextInt();
		int q1 = in.nextInt();
		int d2 = in.nextInt();
		int p2 = in.nextInt();
		int q2 = in.nextInt();
		
		// 2. 在新坐标轴下确定两个点的坐标
		double x1= x[d1]*p1 + x[(d1+2)%6]*q1;
		double y1 = y[d1]*p1 + y[(d1+2)%6]*q1;
		
		double x2 = x[d2]*p2 + x[(d2+2)%6]*q2;
		double y2 = y[d2]*p2 + y[(d2+2)%6]*q2;
		
		double deltaX = Math.abs(x1-x2); // x 轴的一个单位 ,可以是斜着2步 也可以是横着1步
		double deltaY = Math.abs(y1-y2); //  y 轴移动一个单位,需要至少斜着1步
		
		// 2. 观察移动规律:
		// 移动只有2种方式
		// 第一种: 斜着移动: 同时来 x 与 y 轴的变化
		// 第二中: 横着移动: 只会带来 x 轴的变化
		// 移动的总步数 = 斜着 + 横着
        int res = (int)deltaY; // 因为具有y轴差, 因此至少需要斜着走的步数
        
        // 由于斜着走的步数 一定会带来 x 轴的变化;
        // 根据 数组对比, 斜着走1步 一定会带来 0.5的x轴变化, 因此
        // 如果 deltaX- deltaY/2 > 0, 说明即使斜着的步数走完后, x轴上依然有差距, 剩下的为x的步数
        if (deltaX- deltaY/2 > 0) {
            res = res + (int)Math.abs(deltaX - deltaY/2);
        }
        System.out.println(res);
	}
}

总结

核心难点
  1. Java使用数组的方式建立相对坐标系
  2. 由于是求最短的步数, 可能被误导为动态规划问题
  3. 观察运动规律, 比如y轴的运动只能依赖斜着运动
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值