hilbert

 

 

 

hilbert
难度级别: A; 编程语言:不限;运行时间限制:1000ms; 运行空间限制:131072KB; 代码长度限制:102400B
试题描述

图1为1阶Hilbert曲线,它由3条长度为1的线段构成;
图2为2阶Hilbert曲线,它由4条1阶Hilbert曲线用3条长度为1的线段(图2中虚线表示)连接而成;
图3为3阶Hilbert曲线,它由4条2阶Hilbert曲线用3条长度为1的线段(图3中虚线表示)连接而成。


N阶Hilbert曲线由4条N-1阶Hilbert曲线用3条长度为1的线段按图2、图3中的方法连接而成。
假设N阶Hilbert曲线的左下角、左上角、右下角、右上角顶点的坐标分别为(0,0)、(0,2^N-1)、(2^N-1,0)、(2^N-1,2^N-1)。现在给定Hilbert曲线的阶数N和Hilbert曲线上两点的坐标(x0,y0)、(x1,y1)。问沿着Hilbert曲线从(x0,y0)走到(x1,y1),路线的长度是多少。

 
输入
输入文件包含多组测试数据。
第一行,一个整数T,表示测试数据的组数。
接下来的T行,每行五个整数,N、x0、y0、x1、y1。
输出
T行,每行一个整数,其中第i行的整数表示第i组测试数据中沿着Hilbert曲线从(x0,y0)走到(x1,y1)需要走的路线长度。
输入示例
3
1 0 1 1 0
2 2 2 0 1
3 1 5 4 2
输出示例
2
5
36
其他说明
本题共2组测试数据。
测试点1:1<=N<=8;
测试点2:1<=N<=30。
对于全部的数据,1<=T<=500。

 分治法,类似棋盘覆盖,先将问题转化成前缀减法,每次计算先确定是那个区域,再递归调用。

注意棋盘有4种形态,可以通过坐标变换转化成2种。

只是代码有些难写

#include<cstdio>
#include<cctype>
#include<stack>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
typedef long long ll;
ll solve(int n,int x,int y,int inv) {
    if(n==1) {
        if(inv) return x==1&&y==0?3:x+y; 
        else return x==0&&y==1?3:x+y;        
    }
    ll N=(1<<n);
    if(inv) {
        if(x<N/2&&y<N/2) return solve(n-1,x,y,inv^1);
        if(x<N/2&&y>=N/2) return solve(n-1,x,y-(N/2),inv)+(N*N/4);
        if(x>=N/2&&y>=N/2) return solve(n-1,x-(N/2),y-(N/2),inv)+(N*N/4)*2;
        return solve(n-1,N-x-1,(N/2)-y-1,inv^1)+(N*N/4)*3;
    }
    else {
        if(x<N/2&&y<N/2) return solve(n-1,x,y,inv^1);
        if(x<N/2&&y>=N/2) return solve(n-1,(N/2)-x-1,N-y-1,inv^1)+(N*N/4)*3;
        if(x>=N/2&&y>=N/2) return solve(n-1,x-(N/2),y-(N/2),inv)+(N*N/4)*2;
        return solve(n-1,x-(N/2),y,inv)+(N*N/4);      
    }
}
int main() {
    int T=read();
    while(T--) {
        int n=read(),x0=read(),y0=read(),x1=read(),y1=read();
        printf("%lld\n",abs(solve(n,x0,y0,1)-solve(n,x1,y1,1)));           
    }
    return 0;    
}
View Code

 

posted @ 2015-08-05 15:05  wzj_is_a_juruo  阅读(250)  评论(0编辑  收藏  举报