步骤:
列出时间(h:m:s)与度数(rh:rm:rs)之间的方程:
rs=6*s;
各针之间的角度如下:
rm-rs=6*m+(0.1-6)*s;
指针间的度数要在d到360-d之间,即解三个|ax+b|型的不等式:(s为唯一未知数)
可以求出任意一分钟内的秒针取值范围,然后每分钟都求一遍。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
/*定义区间的上下限*/
typedef struct Extent
{
double l,r;
}extent;
double degree;
/*需要degree<|ax + b |<360-dgree即可解不等式*/
extent method(double a,double b)
{
extent p;
if(a > 0)
{
p.l = (degree - b)/a;
p.r = (360 - degree - b)/a;
}
else if(a < 0)
{
p.r = (degree - b)/a;
p.l = (360 - degree - b)/a;
}
if(p.l < 0)
{
p.l = 0;
}
if(p.r > 60)
{
p.r = 60;
}
if(p.l >= p.r)
{
p.l = p.r = 0;
}
return p;
}
/*求最大值*/
double max(double a,double b)
{
return a > b ?a:b;
}
/*求最小值*/
double min(double a,double b)
{
return a < b?a:b;
}
/*求交集*/
extent mixed(extent p1,extent p2)
{
extent p;
p.l = max(p1.l,p2.l);
p.r = min(p1.r,p2.r);
if(p.l >= p.r)
{
p.l = p.r = 0;
}
return p;
}
double happytime(int h,int m)
{
extent s[3][2];/*用来保存不等式的解*/
extent x;/*保存交集*/
double a1,a2,a3;
double b1,b2,b3;
a1 = 1/120.0 - 1 /10.0,b1 = h * 30.0 + m /2.0 - m * 6.0;/*hw - mw得到的a1x+b1*/
a2 = 1/120.0 - 6.0,b2 = h * 30.0 + m /2.0;/*hw - sw得到的a2x+b2*/
a3 = 6.0 - 0.1,b3 = -1*m*6.0;/*sw - mw得到的a3x+b3*/
s[0][0] = method(a1,b1);/*s[0]保存不等式degree<|a1x+b1|<360-degree的解*/
s[0][1] = method(-a1,-b1);
s[1][0] = method(a2,b2);/*s[1]保存不等式degree<|a2x+b2|<360-degree的解*/
s[1][1] = method(-a2,-b2);
s[2][0] = method(a3,b3);/*s[2]保存不等式degree<|a3x+b3|<360-degree的解*/
s[2][1] = method(-a3,-b3);
/*然后再s[0],[s1],s[2]中找交集*/
/*把三个不等式的解每次那一个出来,一共有8个交集,把这八个交集的值再并起来,就是把交集区间的值都加起来就是这一分钟的*/
/*happy时间*/
double sum = 0.0;/*保存最终结果*/
for(int i = 0;i < 2;++i)
{
for(int j = 0;j < 2;++j)
{
for(int k = 0;k < 2;++k)
{
x = mixed(mixed(s[0][i],s[1][j]),s[2][k]);
sum += (x.r - x.l);
}
}
}
return sum;
}
int main()
{
int h,m;
double count;
while(1)
{
count = 0.0;
scanf("%lf",°ree);
if(degree == -1)
{
break;
}
for(h = 0;h < 12;++h)
{
for(m = 0;m < 60;++m)
{
count += happytime(h,m);
}
}
printf("%.3lf\n",count/432.0);
}
return 0;
}