• 【算法竞赛进阶指南】分形之城


    题目链接

    思路

    把左上角的坐标看做 \((0 , 0)\),右上角的坐标为 \((0,2^n-1)\),左下角的坐标为 \((2^n-1,0)\),右下角坐标为 \((2^n-1,2^n-1)\)

    街区的标号也从 \(0\) 开始。

    现在对于给定的两个距离,我们要分别求出他们的坐标。

    现在给出等级为 \(2\),距离为 \(10\),如何求坐标呢?

    等级为 \(1\) 的城市中有 \(4\) 座街区,通过 \(10/4 = 2\),可以知道这个街区在 等级为 \(2\) 的右下角,即图中 \(4\) 部分。

    这时如果可以求出它在 \(4\) 中的坐标,横纵坐标都加上 \(2\),就得到了它在等级为 \(2\) 的城市中的坐标。

    求其在 \(4\) 中的坐标可以转化为 求在等级 \(1\) 中,距离为 \(10\%4\) 的坐标 (因为 \(4\) 部分是直接复制的等级为 \(1\) 的城市)

    这样问题就可以递归解决。

    定义函数 \(cal(N,M) 表示求在 N 级城市中,距离起点距离为 M 的坐标\)

    \(cal(N,M)\) 时,\(N-1\) 级城市有 \(2^{2*N-2}\) 座街区,先递归求解 \(cal(N-1,M mod\ 2^{2*N-2})\)

    注意这时还要进行坐标变换:\(4\)部分没有进行是因为它是直接从 \(N-1\) 级城市复制得到的。

    假如在 \(1\) 部分,通过观察可以知道,\(1\) 部分是 \(N-1\) 级城市 顺时针旋转,然后水平翻转得到的。

    如果在 \(2\) 部分,也不需要变换

    如果在 \(3\) 部分,先逆时针旋转90度,然后水平翻转。

    如果在 \(4\) 部分,不需要变换。

    这时已经得到该点在 \(N-1\) 级城市中的坐标。

    那么针对这 \(4\) 部分的点,横纵坐标加上不同的值即可。

    \(1\) 部分不需要加

    \(2\) 部分纵坐标加上 \(N-1\) 级城市的边长

    \(3\) 部分横坐标加上 \(N-1\) 级城市的边长

    \(4\) 部分横纵坐标均加上 \(N-1\) 级城市的边长

    代码

    #include <bits/stdc++.h>
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int mod = 1e9 + 7;
    const double eps = 1e-6;
    const int inf = 0x3f3f3f3f;
    const int N = 2e5 + 10;
    
    pair<ll, ll> cal(ll n, ll now)
    {
        if (n == 0)
            return { 0, 0 };
        ll len = 1LL << (n - 1), cnt = 1LL << (2 * n - 2);
        pair<ll, ll> pre = cal(n - 1, now % cnt);
        ll x = pre.first, y = pre.second;
        int tmp = now / cnt;
        if (tmp == 0) {
            return { y, x };
        } else if (tmp == 1) {
            return { x, y + len };
        } else if (tmp == 2) {
            return { x + len, y + len };
        } else {
            return { 2 * len - y - 1, len - x - 1 };
        }
    }
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while (T--) {
            ll n, a, b;
            scanf("%lld%lld%lld", &n, &a, &b);
            pair<ll, ll> aga = cal(n, a - 1);
            pair<ll, ll> en = cal(n, b - 1);
            double dis = sqrt(pow((aga.first - en.first) * 10, 2) + pow((aga.second - en.second) * 10, 2));
            printf("%.0lf\n", dis);
        }
        return 0;
    }
    
  • 相关阅读:
    第07组 Beta冲刺(2/5)
    第07组 Beta冲刺(1/5)
    第07组 Alpha事后诸葛亮
    第07组 Alpha冲刺(5/6)
    第07组 Alpha冲刺(6/6)
    软工实践个人总结
    第01组 Beta版本演示
    第01组 Beta冲刺(5/5)
    第01组 Beta冲刺(4/5)
    第01组 Beta冲刺(3/5)
  • 原文地址:https://www.cnblogs.com/valk3/p/14034190.html
Copyright © 2020-2023  润新知