POJ 3889 Fractal Streets

POJ 3889 Fractal Streets

Input

On the first line of the input is a positive integer, the number of test cases. Then for each test case:
A line containing a three positive integers, n < 16 and h, o < 231, specifying the order of the Hilbert curve, and the house numbers of the offered house and the local city planning office.

Output

For each test case:
One line containing the distance Chris will have to fly to his work in meters, rounded to the nearest integer.

Sample Input
3
1 1 2
2 16 1
3 4 33
Sample Output
10
30
50

递归

st;ed号房屋在N级城市中的位置,求他们之间的直线距离

思路:

N-1级城市入手,可以通过变换得到在N级城市中的位置

具体思路不写了,书上很清楚,感觉旋转、水平翻转坐标那里不好想

想成一个正方形在滚动,坐标中的xy是长度,翻滚的时候长度不变,然后就可以根据边长推出新坐标了

非常要吐槽,也是平时注意不到的一个地方就是在求sqrt之类的东西是变量的类型,因为poj不支持c++11每次在提交的时候都要改一些东西TAT

#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
/* static const auto io_sync_off = []() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    return nullptr;
}(); */

using ll = long long;//提交需要改成typedef
using paii = pair<ll, ll>;

paii calc(int n, ll m)
{
    if (n == 0)
        return make_pair(0, 0);
    ll len = 1 << n - 1, cnt = 1 << 2 * n - 2;//n-1级城市边长,房屋数量
    paii pos = calc(n - 1, m % cnt);//n-1级城市中的编号为m%cnt
    ll x = pos.first, y = pos.second;
    ll num = m / cnt;//在n-1级城市中哪个城市
    if (num == 0)//左上
        return make_pair(y, x);
    if (num == 1)//右上
        return make_pair(x, y + len);
    if (num == 2)//右下
        return make_pair(x + len, y + len);
    if (num == 3)//左下
        return make_pair(2 * len - y - 1, len - x - 1);
}

int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        int n, st, en;
        cin >> n >> st >> en;
        st -= 1, en -= 1;
        paii stNum = calc(n, st);
        paii enNum = calc(n, en);
        /* cout<<stNum.first<<" "<<stNum.second<<endl;
        cout<<enNum.first<<" "<<enNum.second<<endl; */
        double dx = double(stNum.first - enNum.first);//必须保持类型一致
        double dy = double(stNum.second - enNum.second);
        printf("%.0f\n", (double)sqrt(dx * dx + dy * dy) * 10);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值