1. 程式人生 > >HDU 1006 Tick and Tick

HDU 1006 Tick and Tick

題目概括

輸入:0~120之間的實數變數D,當D為-1時退出

輸出:鐘錶上三個指標兩兩相距大於等於D的時間佔整天時間的百分比

Sample Input

0 120 90 -1

Sample Output

100.000 0.000 6.251

分析

這個問題需要選定時間單位,採用列舉法搜尋,善用區間去除不可能情況,縮短時間消耗。參考 這裡 的思路,程式碼也是仿寫的。
首先,計算三者的角速度(°/s),這裡以 秒 為單位。

秒針: 6 °/s

分鐘:1/10 °/s

時針:1/120 °/s

那麼,兩兩之間的角速度差可以定義為:

秒針和分針 sm = 11/120 °/s

秒針和時針 sh = 719/120 °/s

分針和時針 mh = 11/120 °/s

所以,兩兩之間每相隔1°,需要的時間為:

秒針和分針 t_sm = 120/11 s

秒針和時針 t_sh = 120/719 s

分針和時針 t_mh = 120/11 s

計算出首次滿足角度D的時間和首次不滿足角度D的時間,求三者的交集,分別取最大值和最小值,就是滿足的時間。

/*****************************************************************
*Name:tick and tick
*Time:20180813-seaf1re
參考:https://blog.csdn.net/lianai911/article/details/42807277
由於三者會在12小時後再次相遇,選定12小時區間計算即可。
*****************************************************************/

#include <iostream>
#include <stdio.h>
#include <algorithm>
const double sm = 59.0/10,sh = 719.0/120,mh = 11.0/120; //必須顯式寫成.0的格式,否則會存為整數
const double t_sm = 360*10.0/59,t_sh = 360*120.0/719,t_mh = 360*120.0/11; //走1°的時間 * 360 = 走一圈的時間

using namespace std;

//定義最大值最小值函式
double Min(double a,double b,double c){
    return min(c,min(a,b));
}
double Max(double a,double b,double c){
    return max(c,max(a,b));
}

int main()
{
    double D;

    while(cin >> D && D != -1){
        double b_sm,b_sh,b_mh,e_sm,e_sh,e_mh,start,finish,sum = 0;
        if(D == 0){ //計算邊界情況
            sum = 100;
            printf("%.3lf\n",100.0);
            continue;
        }

        //第一次滿足條件的時間
        b_sm = D / sm;
        b_sh = D / sh;
        b_mh = D / mh;
        //第一次不滿足條件的時間
        e_sm = (360 - D) / sm;
        e_sh = (360 - D) / sh;
        e_mh = (360 - D) / mh;
        //尋找可能的時間,求三種情況的交集.順序可交換
         for (double b1 = b_sm,e1 = e_sm; e1 <= 12 * 60 * 60; b1 += t_sm , e1 += t_sm){
            for (double b2 = b_sh,e2 = e_sh; e2 <= 12 * 60 * 60; b2 += t_sh , e2 += t_sh){
                if(e2 < b1) continue;
                if(b2 > e1) break;
                for (double b3 = b_mh,e3 = e_mh; e3 <= 12 * 60 * 60; b3 += t_mh , e3 += t_mh){
                    if(e3 < b2 || e3 < b1) continue;
                    if(b3 > e1 || b3 > e2) break;
                    start = Max(b1,b2,b3);
                    finish = Min(e1,e2,e3);
                    sum += (finish - start);
                }
            }
        }
        printf("%.3lf\n",sum/(12*60*60)*100);
    }

    return 0;
}