hdoj1006--Tick and Tick

8438 단어 OJ
Problem Description
The three hands of the clock are rotating every second and meeting each other many times everyday. Finally, they get bored of this and each of them would like to stay away from the other two. A hand is happy if it is at least D degrees from any of the rest. You are to calculate how much time in a day that all the hands are happy.
 
Input
The input contains many test cases. Each of them has a single line with a real number D between 0 and 120, inclusively. The input is terminated with a D of -1.
 
Output
For each D, print in a single line the percentage of time in a day that all of the hands are happy, accurate up to 3 decimal places.
 
Sample Input
0
120
구십
-1
 
Sample Output
100.000
0.000
6.251
 
/////////////////////////////
알고리즘 분석
초침(S): 1s 360/60= 6도(degree) 분침(M): 1s 360/60*60= 1/10도(degree) 시침(H): 1s 360/60*60*12= 1/120도(degree)
초침과 분침의 상대 속도는 V(M, S) = 6-1/10 = 59/10 d/s이다.같은 이치로 시침과 초침 V(H, S) = 6-1/120 = 719/120 d/s;V(H,M) = 1/10-1/120 = 11/120 d/s.
초침과 분침의 만남 주기는 T(M, S) = 360/V(M, S) = 3600/59;동일, T(H, S) = 360/V(H, S) = 43200/719;T(H,M)= 360/V(H,M)=43200/11;
하루 24시간 내, 후 12시간은 전 12시간과 상황이 완전히 같기 때문에 12시간만 찾으면 된다.총 12시간 T=12h*60m*60s=43200s
초침과 분침의 만남 횟수는 N(M, S) = T/T(M, S) = 59*12 = 708 동리, N(H, S) = T/T(H, S) = 719 N(H, M) = T/T(H, M) = 11
주기적인 법칙으로 알 수 있듯이 초침과 분침 사이의 각도를 함수 F(t)로 표시하면 F(t)는 어느 순간 t와 두 침 사이의 각도이다.F(t+n*T(M, S)=F(t), 그중 n은 자연수, 동리, F(t+n*T(H, S)=F(t)F(t+n*T(H, M)=F(t)
그래서 우리는 첫 번째 주기 내의 각 지침 간의 행복 시간 구간을 계산하고 몇 개의 각자 주기를 더하면 여전히 행복 구간이다.각도 차가 적어도 D일 때 초침과 분침이 행복하다고 가정하면 첫 번째 주기 T(M, S)에서 D<= V(M, S)*t<= 360-D
t1=D/V(M, S)t2=(360-D)/V(M, S);주기적으로 happy(tms)=(t1+n*T(M, S), t2+n*T(M, S)) 0 <= n마지막으로 삼자의 교차 구간 길이를 구한다
L = happy(t ms) X happy(t hs) X happy(t hm), (X는 관계를 나타낸다) 하면 된다.
    #include <iostream>  
    #include <iomanip>  
    using namespace std;  
    const int T = 360*120, NMS = 708,NHM = 11, NHS = 719;  // 
    const double F = 0.0466631;                            //F ,  
    const double hmlen = T*F/NHM,mslen = T*F/NMS,hslen = T*F/NHS;    
    struct  interval  
    {  
        double low,high;  
    };  
    interval andset(interval S1,interval S2)  
    {  
        interval zone;  
        zone.low  = S1.low > S2.low ? S1.low : S2.low;  
        zone.high = S1.high < S2.high ? S1.high : S2.high;  
        if( zone.low >= zone.high )  
            zone.low = zone.high = 0.0;  
        return zone;  
    }  
    int main()  
    {  
        int D=0;  
        while(cin>>D&&D!=-1)  
        {  
            double len = 0.0;  
            interval ms,hs,hm;  

            hm.low = hmlen*D/360 - hmlen;  
            hm.high = - hm.low -hmlen;  

            ms.low = mslen*D/360 - mslen;  
            ms.high = - ms.low -mslen;  

            hs.low = hslen*D/360 - hslen;  
            hs.high = - hs.low -hslen;  

            for(int i=0,j=0,k=0;i<NHM;i++)  
            {  
                hm.low+=hmlen;  
                hm.high+=hmlen;  

                for(;j<NMS;j++)  
                {  
                    ms.low+=mslen;  
                    ms.high+=mslen;  

                    interval temp1 = andset(hm,ms);  
                    if(temp1.low!=0||temp1.high!=0)  
                    {  
                        for(;k<NHS;k++)  
                        {  
                            hs.low+=hslen;  
                            hs.high+=hslen;  

                            interval temp2 = andset(temp1,hs);  
                            len+=temp2.high-temp2.low;  
                            if(hs.high>=temp1.high)  
                            {  
                                hs.low-=hslen;  
                                hs.high-=hslen;  
                                break;  
                            }  
                        }  
                    }  
                    if(ms.high>=hm.high)  
                    {  
                         ms.low-=mslen;  
                         ms.high-=mslen;  
                         break;  
                    }  
                }  
            }  
            cout<<setprecision(3)<<fixed<<len/(432*F)<<endl;  
        }  
        return 0;  
    }  

좋은 웹페이지 즐겨찾기