98. 分形之城
城市的規劃在城市建設中是個大問題。
不幸的是,很多城市在開始建設的時候並沒有很好的規劃,城市規模擴大之後規劃不合理的問題就開始顯現。
而這座名為 Fractal 的城市設想了這樣的一個規劃方案,如下圖所示:
當城區規模擴大之後,Fractal 的解決方案是把和原來城區結構一樣的區域按照圖中的方式建設在城市周圍,提升城市的等級。
對於任意等級的城市,我們把正方形街區從左上角開始按照道路標號。
雖然這個方案很爛,Fractal 規劃部門的人員還是想知道,如果城市發展到了等級 N,編號為 A 和 B 的兩個街區的直線距離是多少。
街區的距離指的是街區的中心點之間的距離,每個街區都是邊長為 10 米的正方形。
輸入格式
第一行輸入正整數nn,表示測試資料的數目。
以下nn行,輸入n組測試資料,每組一行。
每組資料包括三個整數 N,A,BN,A,B, 表示城市等級以及兩個街區的編號,整數之間用空格隔開。
輸出格式
一共輸出n行資料,每行對應一組測試資料的輸出結果,結果四捨五入到整數。
這是著名的無線包含自身分形的“分形”圖......(請看《演算法進階》)
其實就是按照演算法進階上說的那樣, 先求出子城市的位置,通過一定的翻轉和平移得到該城市的位置, 只是考慮如何變換比較麻煩,在打這道題時還學到一個小小的乾貨:
我把程式碼寫成這樣輸出的總是負數 ll len = 1 << (n - 1), size2 = 1 << (2 * n - 2);
後來看題解寫成這樣就過去了 ll len = 1LL << (n - 1), size2 = 1LL << (2 * n - 2);
LL
其實代表long long
,1LL
是為了在計算時,把int
型別的變數轉化為long long
,然後再賦值給long long
型別的變數。#include <bits/stdc++.h> using namespace std; typedef long long ll; const int INF = 0x3f3f3f3f; const int MAXN = 5e5 + 100; const int MAXM = 3e3 + 10; template < typename T > inline void read(T &x) { x = 0; T ff = 1, ch = getchar(); while(!isdigit(ch)) { if(ch == '-') ff = -1; ch = getchar(); } while(isdigit(ch)) { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); } x *= ff; } template < typename T > inline void write(T x) { if(x < 0) putchar('-'), x = -x; if(x > 9) write(x / 10); putchar(x % 10 + '0'); } ll T, n, a, b; pair < ll, ll > calc(ll n, ll m) { if(n == 0) return make_pair(0, 0); ll len = 1LL << (n - 1), size2 = 1LL << (2 * n - 2); // n - 1級城市中的邊長和房屋數 pair < ll, ll > id = calc(n - 1, m % size2); ll x = id.first, y = id.second; int u = m / size2; // 判斷第幾區域 if(u == 0) return make_pair(y, x); if(u == 1) return make_pair(x, y + len); if(u == 2) return make_pair(x + len, y + len); if(u == 3) return make_pair(2 * len - y - 1, len - x - 1); } int main() { read(T); while(T--) { read(n); read(a); read(b); pair < ll, ll > aa = calc(n, a - 1); pair < ll, ll > bb = calc(n, b - 1); ll dx = aa.first - bb.first, dy = aa.second - bb.second; double ans = sqrt(dx * dx + dy * dy) * 10; printf("%0.lf\n", ans); } return 0; }