其他分享
首页 > 其他分享> > AcWing 98. 分形之城

AcWing 98. 分形之城

作者:互联网

题目传送门

一、理解题意

本题看懂题目花费了大量的时间,后面理解题意如下:
等级一:\(4\)个点,等级二: \(16\)个点,等级三:\(64\)个点... 至于贯穿这些点的线,是城市编号增长的顺序

分析从等级一如何到等级二,原来的城区设为\(A\):

二、数学知识

我们知道,两点之间距离的平方是对应横纵坐标距离之差的平方和。
欧几里得距离

坐标旋转公式:比如第一象限的点(\(1,2\)),顺时针旋转\(90\)度得到的点在第四象限,也就是(\(2,-1\)),逆时针旋转\(90\)度得到的点在第二象限,也就是(\(-2,1\))。更一般的,(\(x,y\))顺时针旋转\(90\)度得到(\(y,-x\)),逆时针得到 (\(-y,x\))。

最重要的是确定坐标原点以及坐标系,大多数人都是按照二维数组的思想,把左上角第一个点作为原点,往下的方向作为\(x\)轴正方向,往右的方向作为\(y\)轴正方向,然后旋转都是绕左上角第一个点旋转,这样造成的问题就是左下角的城区在计算坐标时,逆时针旋转会转偏了,不容易计算。

个人浅见是按照各个等级城区中心为坐标原点:

刚开始一直是以城区一的中心为原点,然后图一的四个点坐标分别为:\((-1,1),(1,1),(1,-1),(-1,-1)\)

以上是以第一行第一列的点为坐标原点(旋转中心)经坐标变换得到其他城区的点的,但是并不能\(ac\),因为图一这样旋转变换得到图二没问题,但是图二绕原来的旋转中心再转就会转歪,后面坐标便不对了。解决办法就是一轮坐标变换后便改变坐标原点(旋转中心),比如等级一经坐标变换后得到等级二的四个坐标后,立刻调整坐标原点(旋转中心)为等级二的中心,再推出等级三坐标,继续调整坐标原点,以此类推。

上面的调整坐标原点是向右下角移动,具体操作为调整原来的坐标,横坐标减小\(len\),纵坐标增加\(len\),也就是在上面推出的坐标后面对横纵坐标再次变换,注意必须先坐标转换再移动坐标原点,即得到:

注意点:
1.代码中坐标公式是两步得到,第一步旋转平移,第二步移动原点。
2.虽然主题代码和\(yxc\)大佬一样,但是输出时是乘以\(5\),看上面我写的关于等级一的四个坐标便可理解,原点不同。

三、实现代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> PII;

PII calc(LL n, LL m) {
    if (n == 0) return {0, 0}; //递归边界
    LL len = 1ll << (n - 1), cnt = 1ll << (2 * n - 2);
    PII pos = calc(n - 1, m % cnt); //上一个等级的坐标信息
    LL x = pos.first, y = pos.second;
    LL z = m / cnt; //处在城区的哪个角
    if (z == 0) return {-y - len, -x + len};
    if (z == 1) return {x + len, y + len};
    if (z == 2) return {x + len, y - len};
    return {y - len, x - len};
}

int main() {
    int T;
    cin >> T;
    while (T--) {
        LL N, A, B;
        cin >> N >> A >> B;
        PII ac = calc(N, A - 1);
        PII bc = calc(N, B - 1);
        double x = ac.first - bc.first;
        double y = ac.second - bc.second;
        printf("%.0lf\n", sqrt(x * x + y * y) * 5);
    }
    return 0;
}

四、疑问解答

\(Q\):有点不理解为啥需要\(10/2=5\)啊?
答:你认真看一下上面的第\(2\)张图,原来\(1\),\(2\)小房子中间的距离是\(len=10\),现在,我们硬生生在它俩中间放上了原点,就相当于把原来的图给细化了一倍,原来的坐标(指以左上角为坐标原点时)\((0,0)\),\((0,1)\)给变成了\((-1,1)\),\((1,1)\),那么边长变可以理解为缩短了一半\(len=10/2=5\)

标签:原点,len,旋转,98,分形,坐标,得到,等级,AcWing
来源: https://www.cnblogs.com/littlehb/p/16419061.html