1. 程式人生 > >希爾伯特曲線

希爾伯特曲線

解釋 部分 矩陣 png can time 連接 逆時針 class

希爾伯特曲線是以下一系列分形曲線 Hn 的極限。我們可以把 Hn 看作一條覆蓋 2^n × 2^n 方格矩陣的曲線,曲線上一共有 2^n × 2^n 個頂點(包括左下角起點和右下角終點),恰好覆蓋每個方格一次。

[p1.png]

Hn(n > 1)可以通過如下方法構造:
1. 將 Hn-1 順時針旋轉90度放在左下角
2. 將 Hn-1 逆時針旋轉90度放在右下角
3. 將2個 Hn-1 分別放在左上角和右上角
4. 用3條單位線段把4部分連接起來

對於 Hn 上每一個頂點 p ,我們定義 p 的坐標是它覆蓋的小方格在矩陣中的坐標(左下角是(1, 1),右上角是(2^n, 2^n),從左到右是X軸正方向,從下到上是Y軸正方向),

定義 p 的序號是它在曲線上從起點開始數第幾個頂點(從1開始計數)。

以下程序對於給定的n(n <= 30)和p點坐標(x, y),輸出p點的序號。請仔細閱讀分析源碼,填寫劃線部分缺失的內容。

#include <stdio.h>

long long f(int n, int x, int y) {
    if (n == 0) return 1;
    int m = 1 << (n - 1);
    if (x <= m && y <= m) {
        return f(n - 1, y, x);
    }
    
if (x > m && y <= m) { return 3LL * m * m + f(n - 1, , m * 2 - x + 1); // 填空 } if (x <= m && y > m) { return 1LL * m * m + f(n - 1, x, y - m); } if (x > m && y > m) { return 2LL * m * m + f(n - 1, x - m, y - m); } }
int main() { int n, x, y; scanf("%d %d %d", &n, &x, &y); printf("%lld", f(n, x, y)); return 0; }

註意:只填寫劃線處缺少的內容,不要填寫已有的代碼或符號,也不要填寫任何解釋說明文字等。

根據曲線的走向,加入點位於右下角的部分,右下角顯然是從上面下來(曲線走向),和正確方向的圖案相比,其實y坐標對應著圖案中的x坐標,只不過相反,小圖案邊長為m,就是m - y + 1.

希爾伯特曲線