1.题目翻译

杭电1006链接

1006

输入一个度数d,时针、分针、秒针相互之间的度数大于等于d,输出一天内它们两两度数大于等于d的时间占比

d的范围 [0, 120], 输入-1结束

2. 解题思路

  1. 计算出各针速度
  • 秒针速度 Vs(d/s) = 6度/秒 = 360 / 60 , 60s转360度

  • 分针速度 Vm(d/s) = 0.1度/秒 , Vm(d/m) = 6度/分

  • 时针速度 Vh(d/s) = 1/120度/秒, Vh(d/m) = 0.5度/分 , Vh(d/h) = 30度/时

  1. 计算各针距离0点的度数(顺时针计算)

    假设当前时间为 h:m:s , h和m为整数,s为实数,已知时间和速度可以计算出各针走过的度数(以0点为起点), 得出已下公式

  • 秒针度数 Ss = 6s
  • 分针度数 Sm = 6m + 0.1s
  • 时针度数 Sh = 30h + 0.5m + 1/120 * s
  1. 各针最少要相隔D度,得出三条不等式

D<= |Sh - Sm| <= 360 - D
D<= |Sh - Ss| <= 360 - D
D<= |Sm - Ss| <= 360 - D

代入后得到
D<= |30h - 5.5m - 11/120 * s| <= 360 - D
D<= |30h + 0.5m - 719/120 * s| <= 360 - D
D<= |6m - 5.9s| <= 360 - D

因为h和m是整数可以穷举,s实数不能穷举,所以可以把s设为未知

h和m是已知的,可以将第一个不等式 a = 30h - 5.5m , b = 11/120 ,故不等式变为D<= |a - bs| <= 360 - D , 另外两条不等式同理。这样可以得到统一解,差异只是不同不等式a和b的值不同
算出统一解为
D<=bs-a<=360-D 解得[(a+D)/b,(a+360-D)/b]
D-360<=bs-a<=-D 解得[(a+D-360)/b,(a-D)/b]

总共得到三组集合
U11、U12
U21、U22
U31、U32

需要计算交集组合,既 2的三次方,有9种情况

3. 代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include<stdio.h>

struct Segment
{
double a,b;
};

double fun(int degrees);
struct Segment seq1(double a, double b, int d);
struct Segment seq2(double a, double b, int d);
double getMin(double a, double b, double c);
double getMax(double a, double b, double c);

int main(void){

int degrees;

while(scanf("%d",&degrees) && degrees!=-1) {
double result = fun(degrees);
printf("%.3lf\n", result);
}

return 0;
}


double fun(int degrees){

double totalTime = 0.0;

for(int h =0; h<12; h++){

for(int m =0; m<60; m++){

struct Segment seg[6];
double a = 30.0*h - 5.5*m;
double b = 11.0 / 120;
seg[0] = seq1(a,b, degrees);

seg[1] = seq2(a,b, degrees);
a = 30.0*h + 0.5*m;
b = 719.0 / 120;
seg[2] = seq1(a,b, degrees);
seg[3] = seq2(a,b, degrees);
a = 6.0*m;
b = 5.9;
seg[4] = seq1(a,b, degrees);
seg[5] = seq2(a,b, degrees);

for(int i=0;i<2; i++){
for(int j=2; j<4; j++){
for(int k=4; k<6; k++){
double max = getMin(seg[i].b, seg[j].b, seg[k].b);
double min = getMax(seg[i].a, seg[j].a, seg[k].a);
if(min > max){
continue;
}
totalTime = totalTime + max - min;
}
}
}
}
}
// 43200 12小时秒数
return totalTime / 432;
}



struct Segment seq1(double a, double b, int d){

struct Segment seg;
seg.a=(d+a)/b;
seg.b=(360.0-d+a)/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;

}

struct Segment seq2(double a, double b, int d){

struct 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;
}

double getMin(double a, double b, double c){

if(b<a){
a = b;
}
if(c<a){
a = c;
}
return a;
}

double getMax(double a , double b, double c){

if(b>a){
a = b;
}
if(c>a){
a = c;
}
return a;
}