題目
二進位制手錶頂部有 4 個 LED 代表小時(0-11),
底部的 6 個 LED 代表分鐘(0-59)。
每個 LED 代表一個 0 或 1,最低位在右側。
例如,上面的二進位制手錶讀取 “3:25”。
上圖取自 leetcode Binary Watch,題目也是改自 leecode Binary Watch。
輸入說明
首先會是 1 個正整數 T(0 < T < 20),表示測資的數量。
接下來 T 行每行給定一個非負整數 n 代表當前 LED 亮著的數量。
輸出說明
針對每筆測資輸出所有可能的時間總和,並以分鐘為單位。
(不合理的時間請不要計算,像是”1:66”, “13:00”)
想法
這題主要是要我們窮舉n
顆燈亮著的組合,
其他都是一些有的沒的處理,所以我們首先宣告一個陣列int led[11];
,
代表那十顆燈,當它的值是0
代表沒亮,1
代表亮著,
我這裡是把第0
~5
顆當作分鐘的 1 ~ 32,6
~9
顆當作小時的 1 ~ 8。
然後開始建造遞迴函數。
首先給它兩個參數,分別是:
n
:現在要選第幾顆燈了chosen
:總共已經選幾顆燈了
再來要給它中止點,可能的中止點有:
- 沒有燈可以選了(
n > 10
) - 選到的燈數跟題目要求的一樣(
chosen == on
,其中on
代表題目輸入)
1 | if (n > 10) return; |
由於我們有設定中止點了,所以先放心地把第n
顆 LED 打開(設成1
):led[n] = 1;
再尋找下一顆打開的可能,由於我們選了第n
顆,所以chosen
要加 1:dfs(n + 1, chosen + 1);
再來我們要試試看不選第n
顆的可能,所以先讓第n
顆熄滅(設成0
):led[n] = 0;
再尋找下一顆打開的可能,由於我們沒選第n
顆,所以chosen
不加 1:dfs(n + 1, chosen);
這樣遞迴的部分就完成了,接下來開始有的沒的處理。
題目要求不合理的時間不要計算,所以我們先檢查選這n
顆燈代表的時間合不合理:
由於這隻錶是二進位錶,我宣告了一個變數pow
,讓它先等於 1,
之後每換下一顆燈就再乘以 2。
由於led[i]
會是0
或1
,所以+= led[i] * pow
就只是代表會不會把pow
加進去而已。
先算分鐘數,由於led[i]
會是0
或1
,
所以min += led[i] * pow
就代表會不會把pow
加min
而已,
超過 60 分鐘(>= 60
)代表這是不合理的時間,所以不把它加進總和。
1 | int min = 0; |
再算小時數,由於led[i]
會是0
或1
,
所以hr += led[i] * pow
就代表會不會把pow
加hr
而已,
超過 12 小時(>= 12
)代表這是不合理的時間,所以不把它加進總和。
1 | int hr = 0; |
確保時間是合理的之後,就可以把它加進總和裡了。
1 | sum += hr * 60 + min; |
遞迴函數:
1 | void dfs(int n, int chosen) { |
遞迴函數寫完之後,把輸入輸出搞一搞這題就結束了。
完整程式碼:
1 |
|