hilbert
?
?
?
| hilbert |
| 難度級別: A; 編程語言:不限;運行時間限制:1000ms; 運行空間限制:131072KB; 代碼長度限制:102400B |
| 試題描述 |
| 圖1為1階Hilbert曲線,它由3條長度為1的線段構成;
|
| 輸入 |
| 輸入文件包含多組測試數據。 第一行,一個整數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?
轉載于:https://www.cnblogs.com/wzj-is-a-juruo/p/4704755.html
總結
- 上一篇: c语言中二进制转十进制详解
- 下一篇: layui登录页面写入数据_layuiA