zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    SGU 495 Kids and Prizes 概率DP 或 数学推理
    poj 2799 IP Networks 模拟 位运算
    uva 202 Repeating Decimals 模拟
    poj 3158 Kickdown 字符串匹配?
    uva 1595 Symmetry 暴力
    uva 201 Squares 暴力
    uva 1594 Ducci Sequence 哈希
    uva 1368 DNA Consensus String 字符串
    数字、字符串、列表的常用操作
    if条件判断 流程控制
  • 原文地址:https://www.cnblogs.com/td15980891505/p/5564130.html
Copyright © 2011-2022 走看看