98. 分形之城
城市的规划在城市建设中是个大问题。
不幸的是,很多城市在开始建设的时候并没有很好的规划,城市规模扩大之后规划不合理的问题就开始显现。
而这座名为 Fractal 的城市设想了这样的一个规划方案,如下图所示:
当城区规模扩大之后,Fractal 的解决方案是把和原来城区结构一样的区域按照图中的方式建设在城市周围,提升城市的等级。
对于任意等级的城市,我们把正方形街区从左上角开始按照道路标号。
虽然这个方案很烂,Fractal 规划部门的人员还是想知道,如果城市发展到了等级 N,编号为 A 和 B 的两个街区的直线距离是多少。
街区的距离指的是街区的中心点之间的距离,每个街区都是边长为 10 米的正方形。
输入格式
第一行输入正整数nn,表示测试数据的数目。
以下nn行,输入n组测试数据,每组一行。
每组数据包括三个整数 N,A,BN,A,B, 表示城市等级以及两个街区的编号,整数之间用空格隔开。
输出格式
一共输出n行数据,每行对应一组测试数据的输出结果,结果四舍五入到整数。
这是著名的无线包含自身分形的“分形”图......(请看《算法进阶》)
其实就是按照算法进阶上说的那样, 先求出子城市的位置,通过一定的翻转和平移得到该城市的位置, 只是考虑如何变换比较麻烦;
与《算法进阶》不同的是: 以每个图中的中心为坐标原点, 每两个相邻城市之间的距离为2, 比如一等级中(1,1)和(1,-1)的距离为2,这时len就是1/2( n - 1)级城市的边长, 即1/4n级城市的边长;
在打这道题时还学到一个小小的干货:
我把代码写成这样输出的总是负数 ll len = 1 << (n - 1), size2 = 1 << (2 * n - 2);
后来看题解写成这样就过去了 ll len = 1LL << (n - 1), size2 = 1LL << (2 * n - 2);
LL
其实代表long long
,1LL
是为了在计算时,把int
类型的变量转化为long long
,然后再赋值给long long
类型的变量。#include <bits/stdc++.h> using namespace std; typedef long long ll; const int INF = 0x3f3f3f3f; const int MAXN = 5e5 + 100; const int MAXM = 3e3 + 10; template < typename T > inline void read(T &x) { x = 0; T ff = 1, ch = getchar(); while(!isdigit(ch)) { if(ch == '-') ff = -1; ch = getchar(); } while(isdigit(ch)) { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); } x *= ff; } template < typename T > inline void write(T x) { if(x < 0) putchar('-'), x = -x; if(x > 9) write(x / 10); putchar(x % 10 + '0'); } ll T, n, a, b; pair < ll, ll > calc(ll n, ll m) { if(n == 0) return make_pair(0, 0); ll len = 1LL << (n - 1), size2 = 1LL << (2 * n - 2); // n - 1级城市中的边长的1/2和房屋数 pair < ll, ll > id = calc(n - 1, m % size2); ll x = id.first, y = id.second; int u = m / size2; // 判断第几区域 if(u == 0) return make_pair(- y - len, - x + len); if(u == 1) return make_pair(x + len, y + len); if(u == 2) return make_pair(x + len, y - len); if(u == 3) return make_pair(y - len, x - len); } int main() { read(T); while(T--) { read(n); read(a); read(b); pair < ll, ll > aa = calc(n, a - 1); pair < ll, ll > bb = calc(n, b - 1); double dx = aa.first - bb.first, dy = aa.second - bb.second; double ans = sqrt(dx * dx + dy * dy) * 5; printf("%0.lf ", ans); } return 0; }