• hdu1006


        该问题是我遇到的第一个钟表问题。一开始以为指针是离散的,一格格的走,结果发现精度不够。看了kuangbin大神博客后才知道,原来是要连续处理,解不等式。首先必须清楚以下基本常识:钟上一小格代表6度。时,分,秒的速度比为1:12:720。为了做连续处理,我们只需要枚举每一分钟中符合条件的区间,然后将每分钟的区间长度加起来就得到了总的满足条件的时间。12小时时,三个针再次重合,所以可以以12小时为一个周期来计算即可。始终以12时的位置为0角度。

    在任意的h时,m分:

    时针走过的角度 hm=h*30+0.5*m+1/120*t;

    分钟走过的角度 mm=6*m+0.1*t

    秒钟走过的角度 ms=6*t

    这时候需要满足三个不等式D<=|hm-mm|<=360-D,D<=|hm-ms|<=360-D,D<=|mm-ms|<=360-D. 而且 0<=t<=60.

    以上不等式的解得的交集就是在m时,m分满足条件的区间段。

    #define  _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    double D;
    struct Interval{
        Interval(double l = 0.0, double r = 0.0){ left = l, right = r; };
        double left, right;
        friend Interval Intesection(Interval X,Interval Y){
            Interval res;
            res.left = max(Y.left, X.left);
            res.right = min(Y.right, X.right);
            if (res.left <=res.right)
                return res;
            else
                return Interval(0,0);
        }
        friend Interval Intesection(Interval X, Interval Y, Interval Z){ //重载
            return Intesection(Intesection(X, Y), Z);
        }
    };
    Interval const I(0, 60);
    Interval* inequality(double a, double b){  //解不等式D<=|a+bx|<=360-D和[0,60]交集,保证了b>0
        Interval X((D - 360 - a) / b, (360 - D - a) / b);
        Interval Y(0, (0 - D - a) / b);
        Interval Z((D - a) / b,60);
        X = Intesection(X, I);
        Interval *res=new Interval[2];
        res[0] =Intesection(X, Y), res[1] = Intesection(X, Z);
        return res;
    }
    double length(int h, int m){
        Interval*s1 = inequality(5.5*m-30 * h, 11.0 / 120);
        Interval*s2 = inequality(-30 * h - 0.5*m, 6.0 - 1.0 / 120);
        Interval*s3 = inequality(-6*m, 5.9);
        double res = 0;
        for (int i = 0; i < 2;i++)
        for (int j = 0; j < 2;j++)
        for (int k = 0; k < 2; k++){
            Interval X = Intesection(s1[i], s2[j], s3[k]);
            res += X.right - X.left;
        }
        return res;
    }
    int main(){
        while (~scanf("%lf", &D) && D != -1){
            double res = 0.00;
            for (int h = 0; h < 12; h++){
                for (int m = 0; m < 60; m++){
                    double x = 5.5*m - 30 * h;
                    if ((abs(x)<D&&abs(x + 5.5)<D) || (abs(x)>360 - D&&abs(x + 5.5)>360 - D)) //可以不要这部分,但是有这部分可以减少不必要的计算,节省时间
                        continue;
                    res += length(h, m);
                }
            }
            printf("%.3lf
    ", res/(6*12*6));
        }
        return 0;
    }
  • 相关阅读:
    C# 备份、还原、拷贝远程文件夹
    C#SpinWait和volatile一点温习
    Asp.net Core中使用Redis 来保存Session, 读取配置文件
    C# Round源码
    C# CRC16 和汉明重量
    .net源码调试 http://referencesource.microsoft.com/
    Session.Abandon和Session.Clear的实现和区别
    log4Net 高性能写入和CSV格式
    asp.net 简单记录请求的客户端和服务端 处理时间
    asp.net 用JWT来实现token以此取代Session
  • 原文地址:https://www.cnblogs.com/td15980891505/p/5564130.html
Copyright © 2020-2023  润新知