题目概括
输入:0~120之间的实数变量D,当D为-1时退出
输出:钟表上三个指针两两相距大于等于D的时间占整天时间的百分比
Sample Input
0 120 90 -1
Sample Output
100.000 0.000 6.251
分析
这个问题需要选定时间单位,采用枚举法搜索,善用区间去除不可能情况,缩短时间消耗。参考 这里 的思路,代码也是仿写的。
首先,计算三者的角速度(°/s),这里以 秒 为单位。
秒针: 6 °/s
分钟:1/10 °/s
时针:1/120 °/s
那么,两两之间的角速度差可以定义为:
秒针和分针 sm = 11/120 °/s
秒针和时针 sh = 719/120 °/s
分针和时针 mh = 11/120 °/s
所以,两两之间每相隔1°,需要的时间为:
秒针和分针 t_sm = 120/11 s
秒针和时针 t_sh = 120/719 s
分针和时针 t_mh = 120/11 s
计算出首次满足角度D的时间和首次不满足角度D的时间,求三者的交集,分别取最大值和最小值,就是满足的时间。
/*****************************************************************
*Name:tick and tick
*Time:20180813-seaf1re
参考:https://blog.youkuaiyun.com/lianai911/article/details/42807277
由于三者会在12小时后再次相遇,选定12小时区间计算即可。
*****************************************************************/
#include <iostream>
#include <stdio.h>
#include <algorithm>
const double sm = 59.0/10,sh = 719.0/120,mh = 11.0/120; //必须显式写成.0的格式,否则会存为整数
const double t_sm = 360*10.0/59,t_sh = 360*120.0/719,t_mh = 360*120.0/11; //走1°的时间 * 360 = 走一圈的时间
using namespace std;
//定义最大值最小值函数
double Min(double a,double b,double c){
return min(c,min(a,b));
}
double Max(double a,double b,double c){
return max(c,max(a,b));
}
int main()
{
double D;
while(cin >> D && D != -1){
double b_sm,b_sh,b_mh,e_sm,e_sh,e_mh,start,finish,sum = 0;
if(D == 0){ //计算边界情况
sum = 100;
printf("%.3lf\n",100.0);
continue;
}
//第一次满足条件的时间
b_sm = D / sm;
b_sh = D / sh;
b_mh = D / mh;
//第一次不满足条件的时间
e_sm = (360 - D) / sm;
e_sh = (360 - D) / sh;
e_mh = (360 - D) / mh;
//寻找可能的时间,求三种情况的交集.顺序可交换
for (double b1 = b_sm,e1 = e_sm; e1 <= 12 * 60 * 60; b1 += t_sm , e1 += t_sm){
for (double b2 = b_sh,e2 = e_sh; e2 <= 12 * 60 * 60; b2 += t_sh , e2 += t_sh){
if(e2 < b1) continue;
if(b2 > e1) break;
for (double b3 = b_mh,e3 = e_mh; e3 <= 12 * 60 * 60; b3 += t_mh , e3 += t_mh){
if(e3 < b2 || e3 < b1) continue;
if(b3 > e1 || b3 > e2) break;
start = Max(b1,b2,b3);
finish = Min(e1,e2,e3);
sum += (finish - start);
}
}
}
printf("%.3lf\n",sum/(12*60*60)*100);
}
return 0;
}