天天看点

Tick and Tick HDU - 1006 (模拟+求区间交集)

大致题意:时钟上时针分针和秒针在一天中三者两两之间的夹角大于D 的时间 占一天总时间的百分比

由于前十二个小时 和后十二个小时 完全一样 所以 只需要求 12个小时内的情况,刚开始想根据 两个针重合的次数 来计算所旋转的角度占全部角度的百分比 后来发现 这样做只能求出 两个指针之间 无法和第三个指针建立关系 

想了挺久思维没转过来 (太菜了) 然后看了别人的题解 才发现可以通过相对角速度 把满足 两个指针的旋转区域的开始 时间点和结束时间点求出来,

然后枚举所有区间 并判断在这个区间里 是否有同时满足三个指针的夹角都满足题意的情况  

最后将这三个区间的交集 加到总时间里除以总的时间 再*100 得到 答案

附上代码  特别注意 for循环的条件里 判断结束时间点的溢出时最好保留6位  否则可能会wa  并且角速度的单位都要是°/s 

#include<cstdio>

#include<iostream>

#include<algorithm>

using namespace std;

double MAX(double a, double b, double c)

{

    return max(a,max(b,c));

}

double MIN(double a, double b, double c)

{

    return min(a,min(b,c));

}

int main()

{

    int D;

    double s=360./60. ;    //秒针角速度

    double m=360./3600.; //分针角速度

    double h=360./(3600.* 12) ; //时针角速度

    double sm=s-m;     //秒针与分针的相对角速度

    double sh=s-h;      //秒针与时针的相对角速度

    double mh=m-h;   //分针与时针的相对角速度

    double cyc_sm=360/sm;  // 秒针与分针重合的周期

    double cyc_sh=360/sh;   // 秒针与时针重合的周期

    double cyc_mh=360/mh; // 分针与时针重合的周期

    while(scanf("%d",&D)&&D!=-1)

    {

        double x_sm=D/sm;     //合法的区间周期的起止时间点

        double x_sh=D/sh;

        double x_mh=D/mh;

        double y_sm=(360-D)/sm;

        double y_sh=(360-D)/sh;

        double y_mh=(360-D)/mh;

        double sumtime=0;   //总时间

        double begintime;    

        double endtime;

        for(double begin_sm=x_sm , end_sm=y_sm; end_sm<43200.000001; begin_sm+=cyc_sm , end_sm+=cyc_sm)

        {

            for(double begin_sh=x_sh , end_sh=y_sh; end_sh<43200.000001 ; begin_sh+=cyc_sh , end_sh+=cyc_sh)

            {

                if(end_sm<begin_sh)break;    // 若两个区间没有交集 则把小的区间增加

                if(end_sh<begin_sm)continue;

                for(double begin_mh=x_mh , end_mh=y_mh; end_mh<43200.000001 ; begin_mh+=cyc_mh , end_mh+=cyc_mh)

                {

                    if(end_mh<max(begin_sm,begin_sh))continue;  // 若第三个区间与两个区间的交集没有交集 则退出或者将第三

                    if(begin_mh>min(end_sm,end_sh))break;          // 个区间增加

                    begintime=MAX(begin_sm, begin_sh , begin_mh);  // 交集的初始时间点

                    endtime=MIN(end_sm, end_sh , end_mh);            // 交集的结束时间点

                    if(endtime>begintime)sumtime+=(endtime-begintime);

                }

            }

        }

        printf("%.3f\n",sumtime*100/(3600*12));

    }

}

继续阅读