分形之城

题目描述

城市的规划在城市建设中是个大问题。不幸的是,很多城市在开始建设的时候并没有很好的规划,城市规模扩大之后规划不合理的问题就开始显现。而这座名为 Fractal 的城市设想了这样的一个规划方案,如下图所示: 
 
当城区规模扩大之后,Fractal 的解决方案是把和原来城区结构一样的区域按照图中的方式建设在城市周围,提升城市的等级。对于任意等级的城市,我们把正方形街区从左上角开始按照道路标号。虽然这个方案很烂,Fractal 规划部门的人员还是想知道,如果城市发展到了等级 N,编号为 A 和 B 的两个街区的直线距离是多少。街区的距离指的是街区的中心点之间的距离,每个街区都是边长为 10 米的正方形。  

 

输入

输入包含多组测试数据,第一行有一个整数 T 表示测试数据的数目。 
每组测试数据包含一行三个整数 N, A, B,表示城市等级以及两个街区的编号。 

 

输出

对于每组测试数据,在单独的一行内输出答案,四舍五入到整数。 

 

样例输入

3
1 1 2
2 16 1
3 4 33

 

样例输出

10
30
50

 

提示

对于 30%  的数据,N≤5,T≤10。 
对于 100%  的数据,N≤31,1≤A,B≤22N 。T≤1000。

 

分形,就是通过一定规律无限包含自身。这里,我们可以看出,原图形处于右下角,右上角是它的复制,左上是它顺时针旋转90度,左下是它逆时针旋转。由此,我们可以判断通过递归来实现,我们需要确定的是每一次扩建之后,编号的变化。这里采用一些小技巧,我们令编号从0开始,左上就是原来的(y,x),通过左上,同理推出其他即可。每一次扩建是2^(n-1)的距离变化。至此,n级城市中,某点坐标已经确定了。之后注意double求距离,四舍五入就好了。

这里调用了pair来存储坐标,pair的优点就是它可以合并两个数据为一个变量,坐标恰恰需要这点。

 

代码如下:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
pair<ll,ll>calc(ll n,ll m)
{
    if(n==0)
    {
        return make_pair(0,0);
    }
    ll len=1<<(n-1),cnt=1<<(2*n-2);
    pair<ll,ll>pos=calc(n-1,m%cnt);
    ll x=pos.first,y=pos.second;
    ll z=m/cnt;
    if(z==0) return make_pair(y,x);
    if(z==1) return make_pair(x,y+len);
    if(z==2) return make_pair(x+len,y+len);
    if(z==3) return make_pair(2*len-y-1,len-x-1);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll n,a,b;
        scanf("%lld %lld %lld",&n,&a,&b);
        pair<ll,ll> posa,posb;
        posa=calc(n,a-1);
        posb=calc(n,b-1);
//        printf("%lld %lld\n",posa.first,posa.second);
//        printf("%lld %lld\n",posb.first,posb.second);
        double ans=(double)sqrt((posa.first-posb.first)*1.0*(posa.first-posb.first)+(posa.second-posb.second)*1.0*(posa.second-posb.second))*10;
        printf("%.0lf\n",ans);
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值