Poj P3889 Fractal Streets___规律+dfs+分治

题目大意:

T 组数据,
每组给出3个数 n , h , o
求在分形图中第 n 级情况下,编号为 h o 的两个点之间的距离 10 为多少。
如图:
这里写图片描述
分形图随等级增加而增大即每增加一级:
1.右下角,右上角复制一遍
2.顺时针旋转 90 度,放到左上角
3.逆时针旋转 90 度,放到左下角
4.各部分首尾相连

编号是从左上角那个点开始计 1 ,沿着道路依次计数。

n < 16
h , o < 2 31

分析:

分治,
每次拆成找当前的需要的点 x 在左上,右上,左下,右上哪个部分然后递归过去,
慢慢拆开然后在过程中计算坐标的位置即可。
不过细节略多。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define N 40

using namespace std;

typedef long long ll;

ll num[N];

void dfs(ll n, ll cnt, ll &x, ll &y)
{
    if (n == 1) 
    {
        if (cnt == 1) x = 1, y = 1;
        if (cnt == 2) x = 1, y = 2;
        if (cnt == 3) x = 2, y = 2;
        if (cnt == 4) x = 2, y = 1;
        return;
    }

    ll tot = num[n] * num[n] / 4;
    if (cnt <= tot)
    {
        dfs(n - 1, cnt, y, x);
        return;
    }
    if (cnt <= 2*tot) 
    {
        dfs(n - 1, cnt - tot, x, y);
        y += num[n] >> 1;
        return;
    }
    if (cnt <= 3*tot) 
    {
        dfs(n - 1, cnt - 2*tot, x, y);
        x += num[n]>>1;
        y += num[n]>>1;
        return;
    }
        dfs(n - 1, cnt - 3*tot, y, x);
        x = num[n] - x + 1;
        y = (num[n]>>1) - y + 1;
}


int main()
{
    num[0] = 1; 
    for (int i = 1; i <= 31; i++) num[i] = num[i-1]<<1;

    int T, n;
    ll A, B;
    scanf("%d", &T);
    while (T--)
    {
           scanf("%d %lld %lld", &n, &A, &B);
           ll x1, x2, y1, y2;
           dfs(n, A, x1, y1);
           dfs(n, B, x2, y2);
           ll ans = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2)) * 10 + 0.5;
           printf("%lld\n", ans);
    }
    return 0;

猜你喜欢

转载自blog.csdn.net/gx_man_vip/article/details/81322542