http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=122
題目:給出兩個時刻 t1 (h1:m1), t2 (h2:m2); 其中 h1,h2 表示小時屬於 [1, 12] , m1, m2表示分鐘屬於 [0, 59],t1 到 t2 的間隔跨度小於 12 小時。要求輸出從 t1 到 t2 的間隔內,分針掃過時針(即兩者重疊)有多少次。具體的題意大概就是這樣,弄起來還是有點複雜。最終沒看明白對輸出格式的要求還 wa 一次。
分析:設在某 t ( h : m ) 時刻,時針和分針重疊,則:
m / 60 = ( h + m / 60 ) / 12; ----意義是指標和 12 點方向組成的夾角占整個圓周的佔比;
因此得到兩針重疊時刻滿足: m = h * 60 / 11; (浮點數)
最終相當於在一個圓環上有 11 個點,每當時針指向這11個點是,即為時針分針重疊的時刻。這 11 個時刻點是:
0 點 0 分,1 點 5.45 分,2 點 10.90 分,3 點 16.36 分, 4 點 21.81 分,...,10 點 54.55 分,共11個點。在中用紅色點給出11個鐘面上時針分針的重合點。
現在問題是給定兩個時刻中間,會夾多少個點(圖中紅點)。題目條件限定時間間隔會小於 12 小時。
解題思路: 首先用一個數組,把 上面的11個點的分鐘浮點數計算後儲存起來。並把這些點用 0 到 10 進行編號(實際上即為該數組的索引)。在實際代碼中實際上是準備了 12 個點,因為首尾兩個點實際是同一點,11:60 分即為 0點0分。但為了判斷方便還是多準備了一個點。
對於一個給定的時刻,我們得出一個結果,即在它和0點之間最靠近它的時刻點的編號。(相當於從 0 點起算,到達該時刻一共會跨越幾個點)。然後我們把兩個時刻的得到的結果相減,就是最終答案(在此間隔內,時針分針重疊了幾次)。
這裡還要對 12 點特別的轉成 0 點去求結果。然後判斷時針走的是哪半圈,即時針只能順時針轉動,如果結束的時刻小,說明它跨越了 12 點,這時候需要對結果加 11 !(因為時針圓周上一共有 11 個重疊時刻點)。特別注意比較時刻大小時,需要把 12 點 m 分當作 0 點 m 分。
#include <stdio.h>double M[12];void Init(){ int i; for(i = 0; i < 12; i++) { M[i] = 60.00 * i / 11; }}int getIndex(int h1, int m1){ if(m1 > M[h1]) return h1; else return h1 - 1;}int main(int argc, char* argv[]){ int h1, m1, h2, m2; int _h1, _h2, index1, index2, result; Init(); printf("Program 3 by team X\n"); printf("Initial time Final time Passes\n"); while(scanf("%d %d %d %d", &h1, &m1, &h2, &m2) != EOF) { _h1 = (h1 >= 12)? 0 : h1; _h2 = (h2 >= 12)? 0 : h2; index1 = getIndex(_h1, m1); index2 = getIndex(_h2, m2); result = (index2 - index1); if((_h1 * 60 + m1) > (_h2 * 60 + m2)) result += 11; printf(" %02d:%02d %02d:%02d%8ld\n", h1, m1, h2, m2, result); } printf("End of program 3 by team X\n"); return 0;}