感谢lyn大佬的指导,感谢CSDN博主「昂昂累世士」的博客
刚开始一直是以城区一的中心为原点,然后图一的四个点坐标分别为:(-1,1),(1,1),(1,-1),(-1,-1)左上角:(x,y)关于原点顺时针90度旋转得到(y,-x)再关于y轴轴对称变换得到(-y,-x);右上角:(x,y)向右平移2len个单位得到(x+2len,y),注意这里的len在代码中有定义;右下角:(x,y)向右平移2len个单位得到(x+2len,y)再向下平移2len个单位得到(x+2len,y-2len);左下角:(x,y)逆时针旋转90度得到 (-y,x),再关于y轴轴对称变换得到(y,x),注意这里四个点的中心是旋转中心,所以只是换了方向,本质四个点还在原地,最后再向下平移2len得到(y,x-2len).
以上是以第一行第一列的点为坐标原点(旋转中心)经坐标变换得到其他城区的点的,但是并不能ac,因为图一这样旋转变换得到图二没问题,但是图二绕原来的旋转中心再转就会转歪,后面坐标便不对了。解决办法就是一轮坐标变换后便改变坐标原点(旋转中心),比如等级一经坐标变换后得到等级二的四个坐标后立刻调整坐标原点(旋转中心)为等级二的中心,再推出等级三坐标,继续调整坐标原点,以此类推。
上面的调整坐标原点是向右下角移动,具体操作为调整原来的坐标,横坐标减小len,纵坐标增加len,也就是在上面推出的坐标后面对横纵坐标再次变换,注意必须先坐标转换再移动坐标原点,即得到左上角:(-y,-x)改变坐标得到(-y-len,-x+len);右上角:(x+2len,y)变成(x+len,y+len);右下角:(x+2len,y-2len)变成 (x+len,y-len);左下角:(y,x-2len)变成(y-len,x-len).
————————————————
版权声明:本文为CSDN博主「昂昂累世士」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_30277239/article/details/86930643
#include <iostream> #include <cmath> #include <cstdio> using namespace std; typedef long long ll; typedef pair<ll, ll> pll; // 计算等级为n,当前编号为m 的坐标 pll calc(ll n, ll m) { if(n == 0) return {0, 0}; // 计算当前街区的边长和城市的数量 ll len = 1ll << (n - 1), cnt = 1ll << (2 * n - 2); pll pos = calc(n - 1, m % cnt); ll x = pos.first, y = pos.second; ll z = m / cnt; if(z == 0) return {-y - len, -x + len}; if(z == 1) return {x + len, y + len}; if(z == 2) return {x + len, y - len}; return {y - len, x - len}; } int main() { int T; cin >> T; while(T --) { ll N, A, B; cin >> N >> A >> B; pll ac = calc(N, A - 1); pll bc = calc(N, B - 1); double x = ac.first - bc.first; double y = ac.second - bc.second; printf("%.0lf ", sqrt(x * x + y * y) * 5); } return 0; }