[不规则的街道 - 题目 - Online Judge] https://oj.haizeix.com/problem/239
题目描述
城市扩建的规划是个令人头疼的大问题。规划师设计了一个极其复杂的方案:当城市规模扩大之后,把与原来城市结构一样的区域复制或旋转 90 度之后建设在原来的城市周围(详细地说,将原来的城市复制一遍放在原城市上方,将顺时针旋转 90 度后的城市放在原城市的左上方,将逆时针旋转 90 度后的城市放在原城市的左方),再用道路将四部分首尾连接起来,如下图所示。
容易看出,扩建后的城市的各个房屋仍然由一条道路连接。定义 N 级城市为拥有 22N 座房屋的城市。对于任意等级的城市,从左上角开始沿着唯一的道路走,依次为房屋标号,就能够得到每间房及的编号了。住在其中两间房屋里的人们想知道,如果城市发展到了一定等级,他俩各自所处的房屋之间的直线距离是多少。你可以认为图中的每个格子都是边长为 10 米的正方形,房屋均位于每个格子的中心点上( T 次询问,每次输入等级 N ,两个编号 S、D ,求 S 与 D 之间的直线距离。
输入
第一行输入一个整数 T。
接下来 T 行,每行输入三个整数 N,S,D。(1≤T≤104,1≤N≤31)
输出
对于每次询问输出一行一个整数,表示两点间的直线距离。输出四舍五入到整数。
Code
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
#define S(a) ((a) * (a))
void f(long long n, long long s, long long &x, long long &y){
if (n == 1){
if (s == 1) x = 0, y = 0;
else if (s == 2) x = 0, y = 1;
else if (s == 3) x = 1, y = 1;
else x = 1, y = 0;
return ;
}
long long L = 1LL << (n - 1);
long long block = L * L;
long long xx, yy;
if (s <= block) { // 1: (x, y) -> (y, x)
f(n - 1, s, xx, yy);
x = yy, y = xx;
} else if (s <= 2 * block){ // 2:(x, y) -> (x,y + L);
f(n - 1, s - block, xx, yy);
x = xx, y = yy + L;
} else if (s <= 3 * block){ // 3:(x, y) -> (x + L, y + L)
f(n - 1, s - 2 * block, xx, yy);
x = xx + L, y = yy + L;
} else { // 4:(x, y) -> (2 * L - y - 1, L - x - 1)
f(n - 1, s - 3 * block, xx, yy);
x = 2 * L - yy - 1, y = L - xx - 1;
}
return ;
}
int main(){
cin.tie(0), cout.tie(0);
long long t, n, s, d;
scanf("%lld", &t);
while (t --){
scanf("%lld%lld%lld", &n, &s, &d);
long long sx, sy, dx, dy;
f(n, s, sx, sy);
f(n, d, dx, dy);
printf("%.0lf\n", 10 * sqrt(S(sx - dx) + S(sy - dy)));
}
return 0;
}
解题思路
分型
分型,是指整体图形可以分成若干个部分,每一部分都是整体缩小后的形状。
题目分析
本题是一道典型的分形系统,一个图片,可以分成如下四个区域。
①.所有编号减0,等价于原图顺时针旋转90度,在做轴对称,所有坐标加(0,0)
②.所有编号减4,等价于原图,所有坐标加(0,n)
③.所有编号减8,等价于原图,所有坐标加(n,n)
④.所有编号减12,等价于原图逆时针旋转90度,再做轴对称,所有坐标加(n,0)
坐标变换
N*M的矩阵,坐标为(x,y),坐标从0开始,经过如下操作:
顺时针旋转90度:(x,y)→(y,N-x-1)
逆时针旋转90度:(x,y)→(M-y-1,x)
轴对称:(x,y)→(x,M-y-1)
最终分析
假设,现在已计算得到对应区域点在原图中的坐标为(x,y)
当前城市等级为n,原图等级为n-1,边长为 L = 2 n − 1 L=2^{n-1} L=2n−1
①.(x,y)→(y,L-x-1)→(y,x)
②.(x,y)→(x,y+L)
③.(x,y)→(x+L,y+L)
④.(x,y)→(L-y-1,x)→(L-y-1,L-x-1)→(2L-y-1,L-x-1)