分形之城(0x02 递推与递归)

简介: 笔记

分形之城


题意

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


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


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


41.png


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


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


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


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


思路

43.png

1.z == 0 时,表示要求的房屋在第一个 1 级城市中,1 级城市经过顺时针旋转90°再水平翻转后得到 2 级城市左上角的部分


(0,0) —> (0,0)


(0,1) —> (1,0)


(1,0) —> (0,1)


(1,1) —> (1,1)


所以坐标变换为 (x,y) —> (y,x)


2.z == 1 时,表示要求的房屋在第二个 1 级城市中,1 级城市经过向右平移得到 2 级城市右上角的部分


(0,0) —> (0,2)


(0,1) —> (0,3)


(1,0) —> (1,2)


(1,1) —> (1,3)


所以坐标变换为 (x,y) —> (x,y + len) len为 n - 1级城市的边长


3.z ==2 时,表示要求的房屋在第三个 1 级城市中,1级城市经过向右再向下平移得到 2 级城市右下角的部分


(0,0) —> (2,2)


(0,1) —> (2,3)


(1,0) —> (3,2)


(1,1) —> (3,3)


所以坐标变换表示为 (x,y) —> (x + len, y + len) len为 n - 1级城市的边长


4.z == 3 时,表示要求的房屋在第四个 1 级城市中,1级城市经过逆时针旋转90°再向下平移得到 2 级城市的左下角的部分


(0,0) —> (3,1)


(0,1) —> (2,1)


(1,0) —> (2,0)


(1,1) —> (3,0)


所以坐标 变换表示为 (x,y) —> (2 * len - y - 1, len - x - 1) len为 n - 1级城市的边长


为方便起见,将房屋从 0 开始编号,相应的,求a - 1 b - 1的位置然后计算距离,最后距离乘以 10 即可(因为每个街区都是 10米的正方形)


代码

#include<bits/stdc++.h>
#include<unordered_map>
// #define int long long
#define INF 0x3f3f3f3f
#define mod 1000000007
#define rep(i, st, ed) for (int (i) = (st); (i) <= (ed);++(i))
#define pre(i, ed, st) for (int (i) = (ed); (i) >= (st);--(i))
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
template<typename T> inline T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<typename T> inline T lowbit(T x) { return x & -x; }
const int N = 100;
pair<LL, LL>cal(LL n, LL m) {
  if (n == 0)return { 0,0 };
  LL cnt = 1ll << (2 * n - 2);
  LL len = 1ll << (n - 1);
  pair<LL, LL>t = cal(n - 1, m % cnt); // 求出 n - 1 级地图中的位置
  LL x = t.first, y = t.second;
  LL z = m / cnt; // 在上一级的哪个区域里
  if (z == 0)return { y,x };
  else if (z == 1)return { x,y + len };
  else if (z == 3)return { 2 * len - y - 1, len - x - 1 };
  else return { x + len,y + len };
}
void solve() {
  LL n, a, b; cin >> n >> a >> b;
  pair<LL, LL>p1 = cal(n, a - 1);
  pair<LL, LL>p2 = cal(n, b - 1);
  printf("%.0lf\n", sqrt((p1.first - p2.first) * (p1.first - p2.first) + (p1.second - p2.second) * (p1.second - p2.second)) * 10);
}
signed main() {
  int t; cin >> t;
  while (t--)
    solve();
  return 0;
}



目录
相关文章
|
9月前
|
人工智能 算法
算法提高:组合数学| 容斥原理常见应用
容斥原理常见的问题如下。 (1) 篮球、羽毛球、网球三种运动,至少会一种的有22人,会篮球的有15人,会羽毛球的有17人,会网球的有12人,既会篮球又会羽毛球的有11人,既会羽毛球又会网球的有7人,既会篮球又会网球的有9人,那么三种运动都会的有多少人? (2) 《西游记》《三国演义》《红楼梦》三大名著,至少读过其中一本的有20人,读过《西游记》的有10人,读过《三国演义》的有12人,读过《红楼梦》的有15人,读过《西游记》《三国演义》的有8人,读过《三国演义》《红楼梦》的有9人,读过《西游记》《红楼梦》的有7人。问三本书全都读过的有多少人?
101 0
算法提高:组合数学| 容斥原理常见应用
|
9月前
|
机器学习/深度学习 算法
算法提高:组合数学| 卡特兰数的实现
卡特兰数列是组合数学中在各种计数问题中常出现的数列,其前几项为1,1,2,5,14,42,132,429,1430,4862,16796,58786,208012…… 卡特兰数首先是由欧拉在计算对凸n边形的不同的对角三角形剖分的个数问题时得到的,即在一个凸n边形中,通过不相交于n边形内部的对角线,把n边形拆分成若干三角形,不同的拆分数用Hn表示,Hn即卡特兰数。
83 0
算法提高:组合数学| 卡特兰数的实现
|
算法
算法简单题,吾辈重拳出击 - 动态规划之爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
|
存储 算法 索引
【每日挠头算法题】LeetCode 1337. 矩阵中战斗力最弱的 K 行 —— 二分 + 排序 / 堆
【每日挠头算法题】LeetCode 1337. 矩阵中战斗力最弱的 K 行 —— 二分 + 排序 / 堆
101 0
【每日挠头算法题】LeetCode 1337. 矩阵中战斗力最弱的 K 行 —— 二分 + 排序 / 堆
|
机器学习/深度学习 算法
<<算法很美>>——(六)——回溯算法(下)—N皇后问题
<<算法很美>>——(六)——回溯算法(下)—N皇后问题
<<算法很美>>——(六)——回溯算法(下)—N皇后问题
|
C++
这道「岛屿题」用并查集做就体现出其威力了!
之前的岛屿题,用 DFS 和 BFS 来做要比用并查集更加好做并且高效,但是最对这一道题来说,用并查集要更加好做。
65 0
|
机器学习/深度学习 JavaScript 前端开发
LDUOJ——最小生成树(欧拉函数+思维)
LDUOJ——最小生成树(欧拉函数+思维)
85 0
|
测试技术
PAT乙级 (贪心) 1023、1020
PAT乙级 (贪心) 1023、1020
57 0
|
定位技术
宝岛探险(求岛屿大小,染色法) 宽搜 深搜
宝岛探险(求岛屿大小,染色法) 宽搜 深搜
宝岛探险(求岛屿大小,染色法) 宽搜 深搜
|
存储 缓存 移动开发
动态规划法
动态规划是在20世纪50年代由美国数学家贝尔曼为研究最优控制问题而提出的,当该方法在应用数学中的价值被大家认同以后,在计算机学界,动态规划法成为一种通用的算法设计技术用来求解多阶段决策最优化问题。