河南省第十三届ICPC-B-水题()

本文介绍了一种算法,用于计算蜜蜂在蜂巢六边形网格中从编号为x的格子到编号为y的格子的最短路径,通过坐标转换和特判处理复杂情况,适用于多组查询。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

牛客地址

小F最近在研究蜂巢,如下图所示,这是一个蜂巢的横剖图,每一个格子都是一个正六边形,多个格子平铺构成一个无限大的平面。我们以中央的格子作为原点,按照下图规律,一圈一圈向外将每个格子都编上号。

在这里插入图片描述

小F想知道,如果一个蜜蜂当前在编号为x的格子处,它想到达编号为y的格子,最优情况下它最少需要经过多少个格子(包含起点终点)。蜜蜂在蜂巢里只能爬行,也就是说它每次只能爬到相邻的格子里。
你需要支持多组询问。

题意:
题目写得很明白()

题解:
直接建坐标系,六边形有三个轴,任选其中两个轴建系即可(某憨憨不想写太多特判然后建了两个系)
然后注意要加特判,具体形式就是正三角形内的两点距离要特判(见代码)

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const ll N = 2e5 + 7, M = 1e9 + 7;
ll x[N], xn[N], y1_[N], y1n[N], y2[N], y2n[N];
ll xx1, xx2, yy;
void pre() {
    x[0] = xn[0] = y1_[0] = y1n[0] = y2[0] = y2n[0] = 1;
    for (ll i = 1; i < N; i++) {
        x[i] = x[i - 1] - 1 + i * 6;
        xn[i] = xn[i - 1] + i * 6 - 4;
        y1_[i] = y1_[i - 1] - 2 + i * 6;
        y1n[i] = y1n[i - 1] - 5 + i * 6;
        y2[i] = y2[i - 1] + i * 6 - 3;
        y2n[i] = y2n[i - 1] + i * 6 - 0;
    }
}

void pos(ll ind) {
    if (ind == 1) {
        xx1 = xx2 = yy = 0;
        return;
    }

    int xi = lower_bound(y2n, y2n + N, ind) - y2n;
    if (ind >= x[xi]) {
        xx1 = xi;
        int k = ind - x[xi];
        xx2 = xi - k;
        yy = -k;
    }
    else if (ind >= y1_[xi]) {
        int k = x[xi] - ind;
        yy = k;
        xx1 = xi - k;
        xx2 = xi;
    }
    else if (ind >= y2[xi]) {
        int k = y1_[xi] - ind;
        xx1 = -k;
        xx2 = xi - k;
        yy = xi;
    }
    else if (ind >= xn[xi]) {
        xx1 = -xi;
        int k = ind - xn[xi];
        xx2 = -xi + k;
        yy = k;
    }
    else if (ind >= y1n[xi]) {
        int k = xn[xi] - ind;
        xx2 = -xi;
        xx1 = -xi + k;
        yy = -k;
    }
    else {
        int k = y1n[xi] - ind;
        xx1 = k;
        xx2 = k - xi;
        yy = -xi;
    }

}


int main() {
    ll T;
    cin >> T;
    pre();
    while (T--) {
        ll a, b;
        cin >> a >> b;
        pos(a);
        ll xa1 = xx1, xa2 = xx2, ya = yy;
        //printf("%lld %lld %lld\n", xa1, xa2, yy);
        pos(b);
        ll xb1 = xx1, xb2 = xx2, yb = yy;
        //printf("%lld %lld %lld\n", xb1, xb2, yy);
        ll suby = abs(ya - yb);
        ll subx1 = abs(xa1 - xb1), subx2 = abs(xa2 - xb2);
        if (suby) {
            if (xa1 > xb1 && ya < yb && subx1 <= suby) {
                subx1 = 0;
            }
            else if (xa1<xb1&& ya>yb&& subx1 <= suby) {
                
                subx1 = 0;
            }
            if (xa2 > xb2 && ya > yb && subx2 <= suby) {
                subx2 = 0;
            }
            else if (xa2 < xb2 && ya < yb && subx2 <= suby) {
                subx2 = 0;
            }
        }
        ll ans = min(subx1 + suby, subx2 + suby);
        cout << ans + 1 << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值