[hihocoder1324]希爾伯特曲線
阿新 • • 發佈:2019-01-08
這是hiho一下 第163周的題目。
題目描述
時間限制:10000ms
單點時限:1000ms
記憶體限制:256MB
描述
希爾伯特曲線是以下一系列分形曲線 Hn 的極限。我們可以把 Hn 看作一條覆蓋 2n × 2n 方格矩陣的曲線,曲線上一共有 2n × 2n 個頂點(包括左下角起點和右下角終點),恰好覆蓋每個方格一次。
Hn(n > 1)可以通過如下方法構造:
將 Hn-1 順時針旋轉90度放在左下角
將 Hn-1 逆時針旋轉90度放在右下角
將2個 Hn-1 分別放在左上角和右上角
用3條單位線段把4部分連線起來
對於 Hn 上每一個頂點 p ,我們定義 p 的座標是它覆蓋的小方格在矩陣中的座標,定義 p 的序號是它在曲線上從起點開始數第幾個頂點。給定 p 的座標,你能算出 p 的序號嗎?
輸入
輸入包含3個整數 n , x , y 。 n 是分形曲線的階數,(x, y)是 p 的座標。
1 ≤ n ≤ 30
1 ≤ x, y ≤ 2n
輸出
p 的序號。
樣例輸入
3 6 1
樣例輸出
60
演算法簡介
方法很簡單,就是按照題目中描述方法對曲線做切割,判斷位置是在左下角或者右上角之類的,然後根據位置切割遞迴。
容易出錯的地方在於這裡面的索引值之類的都是從1開始,所以需要
以及最大的結果為
旋轉的時候題目中所述的是n從小到大構建曲線,但遞迴是從大到小,所以旋轉方向與題目中相反。
程式碼
#include <iostream>
using namespace std;
unsigned long long int cal(unsigned long long int n,unsigned long long int x,unsigned long long int y) {
if (n == (unsigned long long int)1) {
if (x == 1 && y == 1)
return 1;
if (x == 1 && y == 2 )
return 2;
if (x == 2 && y == 2)
return 3;
if (x == 2 && y == 1)
return 4;
}
unsigned long long int one = 1;
bool bigx = (x > (one << (n-one))), bigy = (y > (one << (n-one)));
unsigned long long int result;
if (!bigx && !bigy)
result = (one<<(2*(n-one))) - cal(n-one,(one<<(n-one))+one-y,x) + one;
if (!bigx && bigy)
result = (one<<(2*(n-one))) + cal(n-one,x,y-(one<<(n-one)));
if (bigx && bigy)
result = (one<<(2*(n-one)+one)) + cal(n-one,x-(one<<(n-one)),y-(one<<(n-one)));
if (bigx && !bigy)
result = (one<<(2*n)) - cal(n-one,y,((one<<(n))+one-x))+one;
return result;
}
int main()
{
unsigned long long int n,x,y;
cin >> n >> x >> y;
cout << cal(n,x,y) << endl;
return 0;
}