HDU:1006 Tick and Tick

题目意思:
一个钟表有三根针分别是时针,分针和秒针,有的时候这些针会重合,最终它们厌倦和待在一起,想彼此之前保持一些距离,现在题目中给出一个度数,如果在某一时刻,任意两根针之间的度数都大于等于给出的这个度数,那么这个时间都是这三根针的happytime,现在让计算,三根针的happytime占一天总时间的百分比,并保留三位小数。


解题思路:
我也是参考网上别人写的,代码都和人家的差不多一样,莫怪莫怪......
这道题目是一个数学题目,就是解不等式,假设时针的度数为hh,分针的度数为mm,秒针的度数为ss
时针每秒转的度数是1.0/120,即时针转速是vh = 1.0/120 度/秒
分针每秒转的度数是1.0/10,即分针的转速是 vm = 0.1 度/秒
秒针每秒转的度数是6,即秒针的转速是vs = 6 度/秒
h时m分s秒时:
hh=30*h+m/2+s/120;
mm=m*6+s/10;
ss=6*s;
输入一个度数degree
如果任意两个针的度数都大于等于degree,那么可以得到以下三个不等式。
degree <= |hh - mm| <= 360-degree;
degree <= |hh - ss| <= 360-degree;
degree <= |mm - ss| <= 360-degree;

即解这三个不等式,现在采用的办法是用暴力求解,很容易想到,0点0时0分时,三个针是重合的,然后随着秒针的转动,三个针的角度都发生了改变,到了12点0分0秒的时候,三个针又完全重合,根据常识,很容易想到,12个小时其实是一个周期,因此暴力求解时,只用求12个小时就可以了,解这个题目,就算每一分钟有多少秒时happytime,最终将这些时间累加再除以总时间就得出答案。


#include<iostream>
#include<cstdio>
#include<cstring>
#define max(a,b) a>b?a:b
#define min(a,b) a>b?b:a
using namespace std;
struct qujian//定义名为区间的结构体,求的是每一分钟符合题目要求的时间区间
{
    double _begin;
    double _end;
};
double degree;//题目中要求的两两针之间至少相差的度数
//求解degree<=|a*x+b|<=360-degree
qujian solve(double a,double b)//a为某两个针之间的相对速度,b为两种针,在h时m分0秒时,初始相处的度数
{
    qujian temp;
    if(a < 0)//如果a<0则除a的时候,不等号的方向要改变
    {
        temp._begin = (360 - degree -b)/a;
        temp._end = (degree - b)/a;
    }
    else
    {
        temp._begin = (degree - b)/a;
        temp._end = (360 - degree - b)/a;
    }
    if(temp._begin < 0)//如果符合条件的开始的时刻是负数,那么要将它赋为下限0
        temp._begin = 0;
    if(temp._end > 60)//如果符合条件的结束的时刻是大于60的,那么要将它赋为上限60,
        temp._end = 60;
    if(temp._end <= temp._begin)//如果开始时刻大于等于结束时刻,说明这种情况是无解的,将begin和and置为0
        temp._begin = temp._end = 0;
    return temp;
}
qujian jiaoji(qujian a,qujian b)//求区间交集的函数
{
    qujian q;
    q._begin = max(a._begin,b._begin);
    q._end = min(a._end,b._end);
    if(q._begin >= q._end)
    {
        q._begin = q._end =0;
    }
    return q;
}
double happytime(int  h,int  m)//关键代码,求h时m分时的happytime
{
    int i,j,k;	//循环变量i,j,k
    double a,b,ans = 0;	//变量a用来存放两种针之间的相对速度,b用来存放两个针之间初始相差的度数
    qujian p;
    qujian q[7];	//存放解区间
    //求degree<=|hh-mm|<=360-degree;
    //h时m分s秒时,时针的角度为
    //hh=30*h+m/2+s/120;
    //mm=m*6+s/10;
    //ss=6*s;
    //下面几行代码求的是在h时m分时时针和分针满足条件的解区间
      //h时m分0,秒时,时针的度数hh = 30*h+m/2.0,分针的度数为mm = m*6;
    a = 1.0/120 - 0.1;//时针对分针的相对速度
    b = 30*h + m/2.0 - 6*m;//当s=0时,此时是h时m分整时时针与分针的夹角
    q[0]=solve(a,b);//这是a*x+b大于零的情况,则去掉绝对值后,a*x+b不改变
    q[1]=solve(-a,-b);//这是a*x+b小于零的情况,则去掉绝对值后,变为-a*x-b;
    //求degree <=|hh-ss|<=360-degree;
      //h时m分0秒时,时针的度数hh= 30*h + m/2.0 ,秒针的度数为 ss = 0;
    a = 1.0/120 - 6;//时针对秒针的相对速度
    b = 30*h + m/2.0;//h时m分整的时候,时针与秒针的夹角
    q[2]=solve(a,b);
    q[3]=solve(-a,-b);
    //求degree<=|mm-ss|<=360-degree;
      //h时m分0秒时,分针的度数为mm = m*6;秒针的度数为 ss = 0;
    a=0.1 - 6;//分针对秒针的相对速度
    b=6*m;//初始时s=0则,mm-ss最初为6*m
    q[4]=solve(a,b);
    q[5]=solve(-a,-b);
      //任取三个不同不等式解出的解求出的交集,就是h时m分,满足时针,分针,秒针两两之间的夹角大于等于degree的时间区间
    for(i = 0; i < 2; i++)
        for(j = 2;j < 4; j++)
            for(k = 4; k < 6; k++)
    {
        p = jiaoji(jiaoji(q[i],q[j]),q[k]);
        ans += p._end - p._begin;//将没次求得的时间加到ans上面
    }
    return ans;//返回答案
}
int main()
{
    while(~scanf("%lf",°ree))
    {
        if(degree == -1)
            break;
        int i,j;
        double sum = 0;
        for(i = 0; i < 12; i++)//0~12小时
            for(j = 0; j < 60; j++)//0~60分钟
            {
                sum += happytime(i,j);//求i时j分的happytime.
            }
        printf("%.3lf\n",(sum*100.0)/(12*3600));
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值