1 条题解

  • 0
    @ 2025-4-8 21:20:21

    解题思路:

    计算在特定六边形网格布局下两点间的最短距离。先把笛卡尔坐标映射到六边形网格坐标,再结合网格特点算出网格内的最短路径,同时考虑两点到对应网格点的距离,综合得到最终最短距离。

    分析:

    1.贪心思想:在 tra 函数中,当将笛卡尔坐标转化为网格坐标时,对于每个初始映射得到的网格点,会遍历其周围六个相邻的网格点,计算每个相邻点到实际笛卡尔坐标点的距离,然后选择距离最近的网格点作为最终映射的网格坐标。这种每次都选择当前最优(距离最近)的选择,体现了贪心算法的思想,虽然这种局部最优选择不一定能保证全局最优,但在这个坐标映射的场景下,能得到一个较为合理的网格坐标表示。

    2.距离计算:使用欧几里得距离公式 dis 函数计算两点间的直线距离,这是基础的几何计算。同时,在计算网格内两点间的距离时,充分利用了六边形的几何特性。例如,根据六边形的边长和角度关系(如 sin(pi/3) )计算出网格的垂直和水平间距,并且在 solve 函数中根据网格坐标的差值(水平和垂直方向)结合六边形的几何特性计算出网格内的路径长度。

    实现步骤:

    1.输入处理:持续读取六边形边长和两点的笛卡尔坐标,直至输入全为 0。

    2.初始化:算出六边形网格的垂直和水平间距,将笛卡尔坐标转为初始网格坐标,优化网格坐标。

    3.距离计算:若两点网格坐标相同,直接返回直线距离;否则,算出网格坐标差值,结合网格几何特性算出网格内距离,再加上两点到对应网格点的距离。

    4.输出结果:以保留三位小数的形式输出最短距离。

    c++实现:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #define max(a,b) ((a)>(b)?(a):(b))
    const double pi = acos(-1.0);
    const int d[6][2] = {{0, 2}, {0, -2}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
    double l, xa, ya, xb, yb, hd, wd;
    int xan, yan, xbn, ybn;
     
    double dis(double x1, double y1, double x2, double y2) {
        return sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
    }
     
    void tra(int &x, int &y, double xa, double ya) {
        if (x % 2) {
    	if (y % 2 == 0) {
    	    y++;
    	}
        }
        else {
    	if (y % 2) {
    	    y++;
    	}
        }
        int minx = x, miny = y;
        double mind = dis(x * wd, y * hd, xa, ya);
        for (int i = 0; i < 6; i++) {
    	double xx = (d[i][0] + x) * wd;
    	double yy = (d[i][1] + y) * hd;
    	if (mind > dis(xx, yy, xa, ya)) {
    	    minx = d[i][0] + x;
    	    miny = d[i][1] + y;
    	    mind = dis(xx, yy, xa, ya);
    	}
        }
        x = minx; y = miny;
    }
     
    void init() {
        hd = sin(pi/3) * l;
        wd = l + l / 2;
        xan = xa / wd;
        yan = ya / hd;
        xbn = xb / wd;
        ybn = yb / hd;
        tra(xan, yan, xa, ya); tra(xbn, ybn, xb, yb);
    }
     
    double solve() {
        if (xan == xbn && yan == ybn)
    	return dis(xa, ya, xb, yb);
        int xx = abs(xbn - xan), yy = abs(ybn - yan);
        double ans = dis(xa, ya, xan * wd, yan * hd) + dis(xb, yb, xbn * wd, ybn * hd) + xx * sin(pi/3) * 2 * l;
        if (yy > xx)
    	ans += (yy - xx) * l * sqrt(3) / 2;
        return ans;
    }
     
    int main() {
        while (~scanf("%lf%lf%lf%lf%lf", &l, &xa, &ya, &xb, &yb) && l || xa || ya || xb || yb) {
    	init();
    	printf("%.3lf\n", solve());
        }
        return 0;
    }
    
    • 1

    信息

    ID
    519
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    15
    已通过
    1
    上传者