1.题目翻译 杭电1006链接
输入一个度数d,时针、分针、秒针相互之间的度数大于等于d,输出一天内它们两两度数大于等于d的时间占比
d的范围 [0, 120], 输入-1结束
2. 解题思路
计算出各针速度
秒针速度 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度/时
计算各针距离0点的度数(顺时针计算)
假设当前时间为 h:m:s , h和m为整数,s为实数,已知时间和速度可以计算出各针走过的度数(以0点为起点), 得出已下公式
秒针度数 Ss = 6s
分针度数 Sm = 6m + 0.1s
时针度数 Sh = 30h + 0.5m + 1/120 * s
各针最少要相隔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" ,°rees) && 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; } } } } } 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; }