【APCS】2023年6月實作題 C++ 解題筆記(前兩題)
【APCS】2023年6月實作題 C++ 解題筆記(前兩題)
此筆記僅供個人學習用途,內容僅供參考。
題目說明:
給定一個如數學座標一樣的二維平面(y 正為北, x 正為東),起始位置於 $(0, 0)$ 。輸入給 $n$ 個座標,必須按照這些點的順序移動,題目保證只會垂直或水平方向移動,不會斜向移動。且第一個點保證一定是 x 軸正的位置(初始方向向右)。
請輸出這條路徑中,左轉、右轉、迴轉的個數分別為多少。
解題思路:
- 定義方向:
- 0:東。
- 1:北。
- 2:西。
- 3:南。
- 計算方向:
- 根據相鄰兩點的座標變化,去判斷移動方向。如:若 x 不變,y 增加,則方向為北(1);若 x 增加,y 不變,則方向為東(0)。
- 判斷轉向:
- 每點 $p_i$ ( $i$ 從 $1$ 到 $n-1$ ),分別計算兩個方向:
- 進入方向 d1:從 $P_{i-1}$ 到 $P_i$ 。
- 離開方向 d2:從 $Pi$ 到 $P_{i+1}$ 。
- 判斷 d1, d2 變化量 dir:
- dir = (d2 - d1 + 4) % 4
- dir == 1:左轉
- dir == 3:右轉
- dir == 2:迴轉
- dir == 0:無轉向
- 每點 $p_i$ ( $i$ 從 $1$ 到 $n-1$ ),分別計算兩個方向:
1 |
|
int dir = (d2 - d1 + 4) % 4; 這條後面的 + 4 是避免方向差 d2 - d1 出現負數的情況,另外用 % 4 取模運算確保落在範圍 $[0, 3]$ 。
至於為何要 d2 - d1 呢?
- 左轉:+ 90 度。
- 右轉:- 90 度。
- 迴轉:+ 180 度或 - 180 度都算迴轉。
因為左轉、右轉等等這些都是需要搭配兩點去判斷的,如果我們知道兩點的角度差,就可以去判斷是左轉還右轉,那這個角度差其實可以用方向來表示(題目保證只有水平跟垂直,所以不管怎樣走都是 90 度),例如 d1 向西(2)、d2 向北(1),還是 d1 向北(1)、d2 向西(2),他們之間的差值都是 1,只是會有正負問題,那這樣我們就可以定義 1 為左轉,剩下的依此類推。
題目說明:
給定一個 $n \times m$ 二維矩陣 $a$ ,每個元素 $a[i][j]$ 的值為 $x (0 \leq x \leq 9)$ 。對於位置 $(i, j)$ ,若以 $(i, j)$ 為中心,曼哈頓距離 $\leq x$ 的所有點的數值總和對 $10$ 取模等於 $x$ ,則稱 $(i, j)$ 為特殊位置。
曼哈頓距離定義:設兩點 $(a, b), (c, d)$ ,則其曼哈頓距離為 $|a - c| + |b - d|$ 。
解題思路:
這題可用 BFS 優化,但老話一句,這是 APCS 第二題,所以你懂的,可以用暴力解 :)。
- 判斷特殊位置:
- 獲取該位置的值 $x = a[i][j]$ 。
- 計算所有曼哈頓距離 $\leq x$ 的點(含 $(i, j)$ )的數值總和。
- 檢查總和對 $10$ 取模是否 $= x$ 。
- 若滿足上述條件,紀錄該特殊位置(記得建一個 vector 來記錄,然後用 pair 容器)。
- 計算曼哈頓距離:
- 設兩點 $(p, q)$ ,用來找所有曼哈頓距離 $\leq x$ 的點,並累計 $a[p][q]$ 的數值總和。
- 曼哈頓距離: $|i - p| + |j - q| \leq x$
- 找 p 點範圍:
- p 要讓 $|i - p| \leq x$ 。
- 拆開絕對值後: $i - x \leq p \leq i + x$ 。
- 要注意 p 他是索引值,所以範圍要再改一下: $0 \leq p \leq n - 1$ 。
- 最後才會變成以下程式碼:
for (int p = max(0, i - x); p <= min(n - 1, i + x); p++)
- 找 q 點範圍:
- 把 p 點固定,令 $|i - p| = dp$ ,則 $|j - q| \leq x - dp = d$ 。
- 所以 q 滿足 $j - d \leq q \leq j + d$ 。
- q 也是索引值,所以:
for (int q = max(0, j - dp); q <= min(m - 1, j + dp); q++)- 另外
int dp = x - abs(i - p);。
註:這個 dp 不是那個 dynamic programming,是代表 i 跟 p 之間的距離。
範例程式碼:
1 |
|
這題比較麻煩的是要推導曼哈頓距離的不等式,之後再透過寫程式的方式枚舉所有可能點。



