zoukankan      html  css  js  c++  java
  • 1006ac(转)

    开始我以为是一秒一秒动,后来才想到是连续的 
    本题目采用解方程方法  利用22针的度数差值函数  解方程
    Vs = 6度每秒 (60秒走一圈360度 360/60=6)
    Vm = 1/10度每秒(3600秒,一个小时走一圈, 360/3600=0.1)
    Vh = 1/120度每秒(12小时走一圈,360/(3600*12)= 1/120)

    然后,就可以得到每两根之间的速度差了:
    Vsm = Vs - Vm = 6 - 1/10 = 59/10
    Vsh = Vs - Vh = 6 - 1/120 = 719/120
    Vmh = Vm - Vh = 1/10 - 1/120 = 11/120
    (算法:Vsm * t = 180 ,所以 t = 180/Vsm = 180 /(59/10) = (180 * 10)/ 59
    所以:
    Dsm = (59/10) * t   或者  360 - (59/10) * t  
    Dsh = (719/120) * t 或者  360 - (719/120) * t
    Dmh = (11/120) * t  或者  360 - (11/120) * t

    #include<iostream>
    #include<iomanip>
    using namespace std;
    const int N=3000;
    typedef struct    //每个区间的结构
    {
     double x,y;
    }TypePoint;
    TypePoint A[N],B[N],C[N],D[N],E[N];    
    int i,j,z,m,n;
    int JiaoJi(TypePoint a[],int s,TypePoint b[],int h,TypePoint c[],int k)  //求时间区间交集
    {
       int q,p;
       k=0;
       
       for(q=0; q<s; q++)
       for(p=0; p<h; p++)
       { 
        if( a[q].x <= b[p].x && a[q].y >= b[p].x && a[q].y <= b[p].y )    //求时间区间交集 有4种情况
        { c[k].x=b[p].x;  c[k++].y=a[q].y; }
        
        if( b[p].x <= a[q].x && b[p].y >= a[q].x && b[p].y <= a[q].y )
        { c[k].x=a[q].x;  c[k++].y=b[p].y; }
        
        if( a[q].x >= b[p].x && a[q].y <= b[p].y )
        { c[k].x=a[q].x;  c[k++].y=a[q].y; }
        
        if( b[p].x >= a[q].x && b[p].y <= a[q].y )
        { c[k].x=b[p].x;  c[k++].y=b[p].y; }
       }
       return k;      //还回交集数组的大小
    }
    int main()
    {
        double d, t, Tsum=43200.0;  //度,happytime的时间,总时间(12个小时即可)
     double Vsm=59.0/10, Vmh=11.0/120, Vsh=719.0/120;    //每2个针的度数差值  second minute hour 
        double Tsm=3600.0/59, Tmh=43200.0/11, Tsh=43200.0/719;   //每2个针的度数差值函数的周期
     double Tsm1, Tsm2, Tmh1, Tmh2, Tsh1, Tsh2;   //记录第一个周期中,每2个针的度数差的时间区间
     int f1, f2, f3, g;
     while( cin>>d && d!=-1 )
     {
      if( d==0 )   //度数为零的情况
      { cout<< setprecision(3) << setiosflags(ios::fixed) <<100.0 <<endl;
          continue;
      }
      if( d>=120 )  //大于120度时 概率为0
      { cout<< setprecision(3) << setiosflags(ios::fixed) <<0.0 <<endl;
          continue;
      }
            Tsm1=d/Vsm;  Tsm2=Tsm - Tsm1;      //计算第一个周期内的 每2个针的度数差的时间区间
      Tmh1=d/Vmh;  Tmh2=Tmh - Tmh1;
      Tsh1=d/Vsh;  Tsh2=Tsh - Tsh1;
      
         i=0;  j=0; z=0; 
      f1=0; f2=0; f3=0;
            while(1)        //分别保存每个周期内符合的时间区间
      {
       if( Tsm1 <= Tsum )
       {  
          A.x = Tsm1;  Tsm1 += Tsm;
          
          if( Tsm2 <= Tsum )
          {  A.y = Tsm2;  Tsm2 += Tsm;  }
          i++;
       }
       else
        f1=1;
                if( Tmh1 <= Tsum )
       {  
          B[j].x = Tmh1;  Tmh1 += Tmh; 
          
          if( Tmh2<=Tsum )
          {  B[j].y=Tmh2;  Tmh2+=Tmh;  }
          j++;
       }
       else
        f2=1;
       if( Tsh1 <= Tsum )
       {  
          C[z].x = Tsh1;  Tsh1 += Tsh; 
          
          if( Tsh2 <= Tsum )
          {  C[z].y = Tsh2;  Tsh2 += Tsh;  }
          z++;
       }
       else
        f3=1;
       if( f1==1 && f2==1 && f3==1)   //三种情况都保存后 退出循环
        break;
      }
            m=0; n=0;
         m=JiaoJi(A, i, B, j, D, m);    //两两求时间区间的交集
            n=JiaoJi(D, m , C, z, E, n);
      t=0;
            for(g=0; g<n; g++)        //将最后的时间区间交集,求出符合Happytime的总时间
       t=t+( E[g].y-E[g].x);
            cout<< setprecision(3) << setiosflags(ios::fixed) << (t/Tsum)*100<<endl;
     }
     return 0;
    }

    一种方法,记录一下,以便日后查找…… Problem Description The three hands of the clock are rotating every second and meeting each other many times everyday. Finally, they get bored of this and each of them would like to stay away from the other two. A hand is happy if it is at least D degrees from any of the rest. You are to calculate how much time in a day that all the hands are happy. Input The input contains many test cases. Each of them has a single line with a real number D between 0 and 120, inclusively. The input is terminated with a D of -1. Output For each D, print in a single line the percentage of time in a day that all of the hands are happy, accurate up to 3 decimal places. Sample Input 0 120 90 -1 Sample Output 100.000 0.000 6.251 // ---- 稍加分析,可以发现对时间离散化计数行不通,因为要想达到精度,则必定超时. // ---- 既然离散地统计不行,那就改为统计时间段. 试想,指针之间的夹角是关于时、分、秒的线性函数, // ---- 如果时、分确定,那么我们就得到关于秒的线性不等式组,其解集必定是一些区间的交或并. // ---- 容易从区间的交或并中统计出“快乐时光”的长度. 具体如下: // ---- 设当前的时间为 H:M:S, 其中 0 <= H < 12, 0 <= M < 60, 0 <= S < 60, H,M皆为整数, S为实数 // ---- 于是时针、分针、秒针相对于时刻 0:0:0 的转角分别为 // ---- A(H) = 30H + M/2 + S/120; // ---- A(M) = 6M + S/10; // ---- A(S) = 6S; // ---- 设题目中的临界夹角为 D,则“快乐时光”是同时满足以下不等式的解: // ---- D <= | A(H) - A(M) | <= 360-D; (1) // ---- D <= | A(H) - A(S) | <= 360-D; (2) // ---- D <= | A(M) - A(S) | <= 360-D; (3) // ---- 上面各式的绝对值中的形式为 bS - a,(a,b为常数,b>0) 故解的形式为 // ---- [ (a+D)/b, (a+360-D)/b) ] 并 [ (a+D-360)/b, (a-D)/b ], 即两个闭区间的并集. // ---- 设由式(i)得到的解集为 Si1 并 Si2, 那么“快乐时光”在时、分确定的情况下,其秒的解集为 // ---- [0,60] 交 (S11 并 S12) 交 (S21 并 S22) 交 (S31 并 S32) // ---- 上面的集合容易化成 S1 并 S2 并 S3 并 S4 并 S5 并 S6 并 S7 并 S8 的形式,其中 S1,S2,...皆为闭区间. // ---- 求区间的并的总长度没有困难,而这个总长度就是由时、分确定的“快乐时光”的长度. #include #include using namespace std; // 区间结构 struct Segment{ double a,b; }; // 由两个区间求出它们的交(区间) Segment operator *(Segment S1,Segment S2) { Segment seg; seg.a = S1.a>S2.a?S1.a:S2.a; seg.b = S1.b= seg.b ) seg.a = seg.b = 0.0; return seg; } // “快乐时光”临界角度 double D; // 从 D <= bS - a <= D1 中解出区间 Segment makeSeg1(double,double); // 从 D <= a - bS <= D1 中解出区间 Segment makeSeg2(double,double); //--------------------------- 主函数 ---------------------------// int main() { while( cin >> D, D != -1 ) { double totLen = 0.0; // “快乐时光”总长度 // 枚举时、分 for(int H = 0; H < 12; H++) { for(int M = 0; M < 60; M++) { Segment S[3][2]; // 获得基本解区间 double a, b; a = 30.0 * H - 5.5 * M, b = 11.0/120; S[0][0] = makeSeg1(a,b), S[0][1] = makeSeg2(a,b); a = 30.0 * H + 0.5 * M, b = 719.0/120; S[1][0] = makeSeg1(a,b), S[1][1] = makeSeg2(a,b); a = 6.0 * M, b = 5.9; S[2][0] = makeSeg1(a,b), S[2][1] = makeSeg2(a,b); // 将解集转化为区间的并,并累计“快乐时光”的长度 for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) for(int k = 0; k < 2; k++) { Segment TS = S[0][i] * S[1][j] * S[2][k]; totLen += TS.b - TS.a; } } } // 输出“快乐时光”的比例 cout< 60.0 ) seg.b = 60.0; if( seg.a >= seg.b ) seg.a = seg.b = 0.0; return seg; } // 从 D <= a - bS <= D1 中解出区间 Segment makeSeg2(double a,double b) { Segment seg; seg.a = (a+D-360.0)/b, seg.b = (a-D)/b; if( seg.a < 0.0 ) seg.a = 0.0; if( seg.b > 60.0 ) seg.b = 60.0; if( seg.a >= seg.b ) seg.a = seg.b = 0.0; return seg; }
  • 相关阅读:
    C++之类和对象
    PHP程序设计基础
    PHP函数和MySQL数据库
    HTML语言基础
    文件和目录1(文件属性和权限)
    文件IO
    查找
    使用tcpdump抓包实例
    导入模块的2种方法
    ansible启用sudo执行命令
  • 原文地址:https://www.cnblogs.com/ganeveryday/p/4381144.html
Copyright © 2011-2022 走看看