Acwing-98-分形之城(递推,数学)

链接:

https://www.acwing.com/problem/content/description/100/

题意:

城市的规划在城市建设中是个大问题。

不幸的是,很多城市在开始建设的时候并没有很好的规划,城市规模扩大之后规划不合理的问题就开始显现。

而这座名为 Fractal 的城市设想了这样的一个规划方案,如下图所示:

city.png

当城区规模扩大之后,Fractal 的解决方案是把和原来城区结构一样的区域按照图中的方式建设在城市周围,提升城市的等级。

对于任意等级的城市,我们把正方形街区从左上角开始按照道路标号。

虽然这个方案很烂,Fractal 规划部门的人员还是想知道,如果城市发展到了等级 N,编号为 A 和 B 的两个街区的直线距离是多少。

街区的距离指的是街区的中心点之间的距离,每个街区都是边长为 10 米的正方形。

思路:

根据书上理解的思路,不断根据n-1级的坐标推出n级的坐标,具体推得方法看代码.

代码:

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

PairLL Cal(LL n, LL pos)
{
    if (n == 0)
        return make_pair(0LL, 0LL);//当处在第0级的时候,只有一间房屋,返回0,0
    LL len = 1LL<<(n-1);//n-1级图形的边长
    LL cnt = 1LL<<(2*n-2);//n-1级图形的节点数
    PairLL now = Cal(n-1, pos%cnt);//在下一级的地图中是第几个节点
    LL x = now.first, y = now.second;
    LL p = pos/cnt;
    //从左往右为y轴正方向, 由上往下为x轴正方向,看书一直没发现,一直没搞懂
    if (p == 0)
        return make_pair(y, x);//由在当前坐标先顺时针旋转90度, 得到(y, len-1-x), 同时因为转到上方时顺序颠倒.
        //y轴要对称调换,即变为(y, len-1-(len-1-x) 即(y, x)
    if (p == 1)
        return make_pair(x, y+len);//右上角即当前坐标向右平移.
    if (p == 2)
        return make_pair(x+len, y+len);//右下角即当前坐标向右下平移
    return make_pair(len+len-1-y, len-1-x);//先逆时针旋转90度,得到(len-1-y, x)
        //同时y轴的对调变为(len-1-y, len-1-x),在因为要向下平移x再加上len.
}


int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        LL a, b, n;
        scanf("%lld %lld %lld", &n, &a, &b);
        PairLL aa = Cal(n, a-1);
        PairLL bb = Cal(n, b-1);
        LL lenx = aa.first-bb.first;
        LL leny = aa.second-bb.second;
        double res = (sqrt(double(lenx*lenx+leny*leny))*10);
        printf("%.0lf
", res);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/YDDDD/p/11461820.html