Mirror Clock
鏡子沿 12–6 點連線左右翻轉,真實時間會是 12:00 扣除鏡中時間;分鐘不為 0 時要借 1 小時,小時算出 ≤ 0 就補 12,因為是 12 小時制。
| Attempts | 3 |
|---|---|
| First attempt | 2026-09-22 |
| Solved | 2026-09-22 |
Problem
小朋友 Onuvob 剛學會看時鐘,而且很愛大聲報時間。他的房間牆上有一個大時鐘,對面剛好有一面鏡子。媽媽發現他有時候會報錯時間,經過一番調查之後才知道,他看時鐘沒問題,問題是他有時候看的是鏡子裡的時鐘 🪞。
媽媽說鏡子裡的時間是錯的,但 Onuvob 卻反問道:「我們可以從鏡子裡的時間算回真的時間,對吧?」
對吧?題目要你來回答,答案確實是可以,而且其實不難。
輸入第一行是測資組數 (),接下來 行,每行是鏡中看到的時間,格式是 HH:MM,保證是合法時間。每組輸出一行真實時間,格式一樣是 HH:MM。
老實說這題我壓根沒看題目敘述,只看到了題目名稱、時鐘圖案跟範例測資就知道要幹嘛了。
不過沒看題敘的代價,就是沒注意到這是一個指針時鐘。錶面上只有 1 到 12,沒有 0 點。範例 12:00 → 12:00 其實就在暗示這件事,我的第一版卻會輸出 00:15 這種東西。24 小時制裡它是對的,但題目就真的只是一般的時鐘。
Approach
我一看到範例 10:09 → 01:51 就有想法了:, 直覺就是直接拿 60 去扣分鐘,有點像國中學的「互餘」。
後來想想這個直覺其實有道理。鏡子會把時鐘以 12 點和 6 點的連線為軸左右翻轉。指針原本在 12 點順時針轉了 度,鏡子裡看起來就是逆時針轉了 度,也就是順時針 。
換成時間的語言就是一句話:
| 鏡中 | 真實 | 說明 |
|---|---|---|
| 03 | 09 | 左右對調 |
| 06 | 06 | 在對稱軸上,不動 |
| 12 | 12 | 在對稱軸上,一樣不動 |
| 10 | 01 | 範例,要借位 |
| 11 | 12 | 算出 0 點 → 要寫成 12 |
| 12 | 11 | 算出 -1 點 → 要補 12 |
減法的細節跟小學直式減法一樣,分鐘不夠減就跟小時借 1:
所以分兩種情況:
-
:時 ,分
-
:時 ,分
最後再把小時拉回 1 到 12:算出來 就 。
Wrong attempts
第一次 WA:沒想到 0 點
第一版的 分支直接輸出 11 - h:
} else { printf("%02d:%02d\n", 11 - h, 60 - m);}鏡中 11:45 會算出 ,輸出 00:15,但錶面上沒有 0 點,正確答案是 12:15。一樣是只跑了題目給的範例就送出,而範例剛好沒有碰到這個 case 😂
第二次 WA:只修了 0,沒修到負數
於是我補了一個三元運算,把 0 換成 12:
} else { printf("%02d:%02d\n", 11 - h == 0 ? 12 : 11 - h, 60 - m);}還是 WA!?這次我開始自己舉測資,隨便試一個 12:45 就破功了:,輸出 -1:45…,時鐘上根本沒有這種東西呀。
把 時所有 列出來就一目了然:
| 鏡中 | 第二版輸出 | 正確 | |
|---|---|---|---|
| 1 ~ 10 | 10 ~ 1 | ✅ | ✅ |
| 11 | 0 | 12 | ✅ |
| 12 | -1 | -1 | ❌ 應為 11 |
我只處理了 ,但 時會掉到負數。兩個都是「超出 1 到 12」的同一類問題,應該用 一起處理:
printf("%02d:%02d\n", 11 - h == 0 ? 12 : 11 - h, 60 - m);printf("%02d:%02d\n", 11 - h <= 0 ? 11 - h + 12 : 11 - h, 60 - m);、,兩個邊界一次解決。
Solution
加上 補 12 之後就過了:
5 collapsed lines
#include <iostream>#include <cstdio>
using namespace std;
void solve() { int t; int h, m;
while (cin >> t) { for (int i = 1; i <= t; i++) { scanf("%d:%d", &h, &m);
if (m == 0) { if (h == 6 || h == 12) { printf("%02d:00\n", h); } else { printf("%02d:00\n", 12 - h); } } else { printf("%02d:%02d\n", (11 - h <= 0 ? 11 - h + 12 : 11 - h), 60 - m); } } }}6 collapsed lines
int main() { solve();
return 0;}標起來的兩段就是全部邏輯:第 14–19 行處理整點,第 21 行處理借位加上拉回 1 到 12。scanf(“%d:%d”) 會把中間的冒號直接吃掉,就不用自己解析字串了。
Sample Input
212:0010:09Sample Output
12:0001:51驗算:12:00 是整點且 ,原樣輸出;10:09 分鐘不為 0,時 、分 ,得 01:51,答案正確。
錯誤歷程
- WA直接輸出 11 - h,只跑了題目給的範例測資#1
- WA補了 11 - h == 0 → 12,但漏掉當 h = 12 點時,11 - h = -1#2
- AC改成 11 - h <= 0 就 +12,自己多舉了幾個邊界測資就過了#3