ProblemDescription

The three hands of theclock 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 fromthe other two. A hand is happy if it is at least D degrees from any of therest. You are to calculate how much time in a day that all the hands are happy.

钟表的三个指针每一秒都在不停的转动,每一天中,指针会相互重合数次。终于,他们对这种每天搅基搅在一起的生活感到腻烦鸟,于是每个指针都想远离其他指针。当发现自己与其他任一指针的角度为大于或等于D的时候,他自己就会觉得很嗨森。你需要做的是算出他们三个在一天之中能够嗨森的总次数。

 

Input

The input contains manytest cases. Each of them has a single line with a real number D between 0 and120, inclusively. The input is terminated with a D of -1.

输入包含许多测试用例。每一个测试用例接受一个角度D(0<=D<=120)。如果输入-1,表示结束测试用例的输入。 

 

Output

For each D, print in asingle line the percentage of time in a day that all of the hands are happy,accurate up to 3 decimal places.

对于每一个测试用例输入的D,单独输出一行表示三个指针嗨森的时间数在一天中所占的百分比,答案精确到小数点后三位。 

 

SampleInput

0

120

90

-1

 

SampleOutput

100.000

0.000

6.251

 

1、求出两两的相角速度。

2、然后根据这个角速度求出两两的周期(即第一次重合到第二次重合所花的时间,既不满足角度要求的时间)。

3算出符合角度要求的第一次足和第一次不足的时间(即区间的起与止)。

4、在三个时间段上加上各自的周期,再取他的交集即可。

解题:

可看作时针,分针,秒针的起始点都指向12,转一圈后又都指向12,此时经过了12小时,所以算比例时只需计算12小时之内  ( 即43200秒 ) 就行。

时针角速度w1=2*pi/T=360度/(12*60*60秒)

分针角速度w2=360度/(60*60秒)

秒针角速度w3=360度/(60秒)

 

相对角速度:

时针与分针w12=w2-w1=11.0/120

时针与秒针w13=w3-w1=719.0/120

分针与秒针w23=w3-w2=59.0/10;

 

相对周期:(即两针间需要多久出现夹角的循环)

时针与分针 T12=43200.0/11

分针与秒针 T13=43200.0/719

时针与秒针 T23=3600.0/59

 

这样的话就可以把时针和分针,时针和秒针,分针和秒针各自满足条件的集合求交集。显然,代码中利用的是三个for循环来暴力解决。不过有些显然不满足条件的情况即可去除,以减少计算次数。

x[0,1,2]和y[0,1,2]记录的是第一个开始满足条件的时间和第一个开始不满足条件的时间。m[0,1,2],n[0,1,2]则是分别根据相对周期来扩大x[3],y[3]以获得所有满足条件的时间集合,并求交集。

=w*t角度=角速度*时间

#include<iostream>

#include<iomanip>

using namespace std;

const doublew12=11.0/120,w13=719.0/120,w23=59.0/10;

const doubleT12=43200.0/11,T13=43200.0/719,T23=3600.0/59;

double max(doublea,double b,double c)求三个区间起始的最大值

{

    double temp=a>b?a:b;

    return temp>c?temp:c;

}

double min(doublea,double b,double c)求三个区间终止的最小值

{

    double temp=a>b?b:a;

    return temp>c?c:temp;

}

以上两个函数求区间的交集

int main()

{

    double D;

    double x[3],y[3];

    double m[3],n[3];

    double sum,begin,end;

    while(cin>>D&&D!=-1)

    {

        x[0]=D/w12; x[1]=D/w13; x[2]=D/w23;

        y[0]=(360-D)/w12; y[1]=(360-D)/w13;y[2]=(360-D)/w23;

        sum=0.0;

 

       三重循环的顺序是可以打乱的for(m[0]=x[0],n[0]=y[0];n[0]<=43200.000001;m[0]+=T12,n[0]+=T12)

        {

           for(m[1]=x[1],n[1]=y[1];n[1]<=43200.000001;m[1]+=T13,n[1]+=T13)

            {

                if(n[0]<m[1]) 提前判断是否有交集

                    break;

                if(m[0]>n[1])

                    continue;

 

                for(m[2]=x[2],n[2]=y[2];n[2]<=43200.000001;m[2]+=T23,n[2]+=T23)

                {

                    if(n[0]<m[2] ||n[1]<m[2])

                        break;

                    if(m[0]>n[2] ||m[1]>n[2])

                        continue;

 

                    begin=max(m[0],m[1],m[2]);取交集

                    end=min(n[0],n[1],n[2]);

 

                    if(end>begin)

                       sum+=end-begin;

                }

            }

        }

       cout<<setiosflags(ios::fixed)<<setprecision(3)<<sum*100.0/43200<<endl;

    }

    return 0;

}

 

 

列出时间(h:m:s)与度数(rh:rm:rs)之间的方程:

rs=6*s;          rm=6*m+s/10;           rh=30*h+0.5*m+s/120;
各针之间的角度如下:

rm-rs=6*m+(0.1-6)*s;       rh-rs=30*h+0.5*m+(1/120)-6)*s;       rh-rm=30*h+(0.5-6)*m+((1/120)-0.1)*s;

指针间的度数要在d360-d之间,即解三个|ax+b|型的不等式:s为唯一未知数)

可以求出任意一分钟内的秒针取值范围,然后每分钟都求一遍。

#include<stdio.h>
#include <stdlib.h>
struct set
{
    double a,b;
};
double d;
struct set sloveset(double a,doubleb);         
/ * d<=ax+b<360-d 的解 */
struct set intersection(struct set a,struct setb);          / * 给两个集合取交集 */
int main()
{
    int h,m,i,j,k;
    double a1,b1,a2,b2,a3,b3,time;
    struct set answer[3][2],ensemble;
    while(scanf("%lf",&d)&&d!=-1)
    {
        time=0;
        for(h=0; h<12; h++)
        {
            for(m=0;m<60; m++)
            {
                b1=6.0*m;                a1=-5.9;
                b2=30*h+0.5*m;            a2=1.0/120-6.0;
                b3=30*h+(0.5-6)*m;         a3=(1.0/120)-0.1;

/ * 3个绝对值不等式的解集存到answeranswer[0][0] answer[0][1]要取并集剩下两个也是 */
                answer[0][0]=sloveset(a1,b1);              answer[0][1]=sloveset(-a1,-b1);
                answer[1][0]=sloveset(a2,b2);              answer[1][1]=sloveset(-a2,-b2);
                answer[2][0]=sloveset(a3,b3);              answer[2][1]=sloveset(-a3,-b3);

/ * 取过交集后,需要将3个式子的结果取并集所以采用下面的方法

循环的意思就是红黄绿中各取一个求交集(上图表示数组answer*/
                for(i=0;i<2;i++)
                {
                    for(j=0;j<2;j++)
                    {
                        for(k=0;k<2;k++)
                        {
                            ensemble=intersection(intersection(answer[0][i],answer[1][j]),answer[2][k]);
                            time+=ensemble.b-ensemble.a;} } }            }
        }
        time=time*100.0/(12*3600);
        printf("%.3lf\n",time);
    }
    return 0;
}

structset sloveset(double a,double b)
{
    struct set seta;
    if(a>0)
    {
        seta.a=(d-b)/a;
        seta.b=(360-d-b)/a;
    }
    else
    {
        seta.b=(d-b)/a;
        seta.a=(360-d-b)/a;
    }
    if(seta.a<0) seta.a=0;
    if(seta.b>60) seta.b=60;
    if(seta.a>=seta.b) seta.a=seta.b=0;
 / /之前这句放到了ifseta.a<0ifseta.b>60)前面了

    returnseta;              //结果seta.b变成了负的怀疑是seta.b太大了冒了不知对错
}
struct set intersection(struct set a,struct set b)
{
    struct set p;
    p.a=a.a>b.a ?a.a:b.a;
    p.b=a.b<b.b ?a.b:b.b;
    if(p.a>p.b) p.a=p.b=0;
    return p;
}

 

 

posted on 2015-04-24 10:30  星斗万千  阅读(138)  评论(0编辑  收藏  举报