【POJ 3889】Fractal Streets

题目描述

请求出一个等级为 n 的分形图中,编号为 S 的格子到编号为 D 的格子的直线距离。

城市的规划在城市建设中是个大问题。不幸的是,很多城市在开始建设的时候并没有很 好的规划,城市规模扩大之后规划不合理的问题就开始显现。而这座名为 Fractal 的城市设想了这样的一个规划方案,如下图所示:

Fractal Streets

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

算法分析

由于当前等级是由四个上一等级的图形拼成,通过发现当前等级与上一等级图形位置之间的变化关系,递归求解所选标号的位置。

代码实现

#include <cstdio>
#include <cmath>
#include <utility>
#define x first
#define y second
typedef long long int ll;
typedef std::pair<ll,ll> P;
ll power[20];
P calc(ll n,ll loc) {
    if(n==0) return P(1,1);
    P ret;
    if(loc<=power[n-1]) {
        P get=calc(n-1,power[n-1]+1-loc);
        ret.x=get.y;ret.y=(1<<(n-1))+1-get.x;
    }
    else if(loc<=2*power[n-1]) {
        P get=calc(n-1,loc-power[n-1]);
        ret.x=get.x;ret.y=(1<<(n-1))+get.y;
    }
    else if(loc<=3*power[n-1]) {
        P get=calc(n-1,loc-2*power[n-1]);
        ret.x=(1<<(n-1))+get.x;ret.y=(1<<(n-1))+get.y;
    }
    else if(loc<=4*power[n-1]) {
        P get=calc(n-1,power[n-1]+1-(loc-3*power[n-1]));
        ret.x=(1<<n)+1-get.y;ret.y=get.x;
    }
    return ret;
}
inline ll solve(ll n,ll h,ll o) {
    P a=calc(n,h),b=calc(n,o);
    return floor(sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y))*10+0.5);
}
int main() {
    int t;scanf("%d",&t);
    power[0]=1;for(int i=1;i<=16;++i) power[i]=power[i-1]*4; 
    ll n,h,o;
    while(t--) {
        scanf("%lld%lld%lld",&n,&h,&o);
        printf("%lld\n",solve(n,h,o));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/whz2018/article/details/81221335