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));
    }

}
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值