Fractal Streets

题目传送门
这是一道挺有意思的递归问题
在这里插入图片描述
首先我们需要发现不同级分形街道的联系
对于任意一张编号大于2的分形街道来说,右上角右下角的图是由前一张直接平移得到的,左上角的是由前一张顺时针旋转90°得到的,左下角是由前一张逆时针旋转90°得到的
基于这项规律我们可以开始递归
首先我们需要预处理一个边长数组,用来直接获取每一张图的边长
如果一张图中点的编号小于上一张图边长的平方,即可说明这个点是在这张图的左上角的,由此我们可以得到这个点在左下角右上角右下角的判断条件
由每个边的边长通过递归也可以得到这个点的坐标
有了点的坐标当然可以通过两点间距离公式求得距离
在这里距离是需要进行四舍五入的,因此答案要定义成double类型,我在这wa了好几把才发现这个问题

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 40;
ll bc[N]; //存储编号为n的分形图的边长
void find(ll n, ll k, ll &x, ll &y)
{
    
    
    if (n == 1) //处理边界
    {
    
    
        if (k == 1) x = y = 1;
        else if (k == 2) x = 1, y = 2;
        else if (k == 3) x = y = 2;
        else if (k == 4) x = 2, y = 1;
        return;
    }
    ll sz = (bc[n] / 2) * (bc[n] / 2);
    if (k <= sz) //左上
    {
    
    
        dfs(n - 1, k, y, x);
    }
    else if (k <= 2 * sz) //右上
    {
    
    
        dfs(n - 1, k - sz, x, y);
        y += bc[n] / 2;
    }
    else if (k <= 3 * sz) //右下
    {
    
    
        dfs(n - 1, k - 2 * sz, x, y);
        x += bc[n] / 2;
        y += bc[n] / 2;
    }
    else //左下
    {
    
    
        dfs(n - 1, k - 3 * sz, y, x);
        x = bc[n] + 1 - x;
        y = bc[n] / 2 + 1 - y;
    }
}
int main()
{
    
    
    bc[1] = 2;
    for (ll i = 2; i < N; i++)
        bc[i] = bc[i - 1] * 2;
    ll k;
    cin >> k;
    while (k--)
    {
    
    
        ll n, h, o;
        cin >> n >> h >> o;
        ll xh, yh, xo, yo;
        find(n, h, xh, yh);
        find(n, o, xo, yo);
        double res = sqrt((xh - xo) * (xh - xo) + (yh - yo) * (yh - yo)) * 10;
        printf("%.0lf\n", res);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_46126537/article/details/112614590