当前位置: 首页 > 科技观察

FractalCity:递归超典型例子,还是不懂?让我画给你看!

时间:2023-03-13 03:54:17 科技观察

本文转载自微信公众号“吹笛蛋窝”,作者吹笛蛋。转载本文请联系派珀蛋巢公众号。题目城市规划是城市建设中的一大难题。遗憾的是,很多城市在建设之初规划不周,城市扩建后规划不合理的问题开始出现。名为Fractal的城市设想了这样一个规划方案,如下图所示:当城市面积扩大时,Fractal的解决方案是在城市周围建立与原有城市结构相同的区域,如图所示。提升城市档次。对于任何级别的城市,我们从左上角开始放置带有道路标签的方块。尽管这个计划很糟糕,但Fractal规划部门的人仍然想知道这两个街区之间的直线距离是多少,如果城市发展到水平。方块的距离是指方块中心点之间的距离,每个方块是一个边长为米的正方形。输入格式在第一行输入一个正整数n,表示测试数据的个数。接下来n行,输入n组测试数据,每组一行。每组数据包括三个整数N、A、B,分别表示城市级别和两个街区的编号,整数之间用空格隔开。输出格式一共输出多行数据,每行对应一组测试数据的输出结果,结果四舍五入为整数。数据范围输入样例:311221613433输出样例:103050问题解决有不懂的地方,手绘!首先要明确为什么可以用递归:我们要计算第n层的坐标,只需要知道第n-1层的坐标,那么递归怎么想?我们首先规定每一层的坐标系原点是唯一的,如下图所示。那么我们归纳推导出从特殊到一般的规律:如果把第1层的块放在第2层,当第1层放在第2层的左上象限时,有四种情况可以讨论,相当于一个顺时针旋转90°。并沿着y轴翻转(为什么要沿着y轴翻转?因为你注意的是每个数字的位置,如果不翻转,虽然形状对齐了,但是数字的顺序不对齐)水平1放在2级的右上象限,不需要把1级转到2级的右下象限,也不需要把1级转到2级的左下象限,这相当于逆时针旋转90°,沿y轴翻转完成旋转,因为我们现在是从level1到level2,所以坐标系的原点也移动了,所以需要在基础上进行平移level1的原始坐标。那我给你画个图你就明白了。然后你去代码。这里补充一点数学知识:对于一个点(x,y),沿原点顺时针旋转90°,就会变成(y,-x)对于一个点(x,y),沿原点逆时针旋转90°,它将变为(-y,x)对于一个点(x,y),以y轴为对称轴翻转将变为(-x,y)code#include#include#include//sqrt#includeusingnamespacestd;typedeflonglongLL;typedefpairPLL;PLLcalc(LLn,LLm){/**n:level*m:坐标,从0开始计数*/if(n==0)return{0,0};LLlen=1ll<<(n-1);//2^{n-1}本层象限的边长/2LLcnt=1ll<<(2*n-2);//4^{n-1}本层象限容量PLLpos=calc(n-1,m%cnt);//上一层坐标信息LLx=pos.first,y=pos.second;intz=m/cnt;//它在哪个象限?y-len,-x+len};//替换原点在右上象限(x+len,y+len)elseif(z==1)return{x+len,y+len};//替换原点在右下象限(x+len,y-len)elseif(z==2)return{x+len,y-len};//将左下象限反转90°(-y,x)并沿y对称性(y,x)(y-len,x-len)替换原点return{y-len,x-len};}intmain(){intN;cin>>N;while(N--){LLn,m1,m2;cin>>n>>m1>>m2;PLLpos1=calc(n,m1-1);PLLpos2=calc(n,m2-1);doubledelta_x=(double)(pos1.first-pos2.first);双ledelta_y=(double)(pos1.second-pos2.second);//level1中,len为单位长度,象限的一半长度为10/2=5printf("%.0lf\n",sqrt(delta_x*delta_x+delta_y*delta_y)*5);}}参考资料[1]Acwing:https://www.acwing.com[2]98。分形城市:https://www.acwing.com/problem/content/100/