這是HDU,Online Judge上的一道題,http://acm.hdu.edu.cn/showproblem.php?pid=1006閒來沒事,研究的做做,開始思路是模擬每一秒,然後計算滿足條件佔所有時間的比例,最後發現計算結果不夠準確,然後採用了找交集的思路,先用相對角速度,求出兩兩之間多長時間後會出現一次夾角循環,然後找出在12小時內他們相互滿足條件的交集。我這裏給出的參考也是參考了曬代碼網上的參考答案。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
using namespace std;
#define CIRCLE 43200.000001
//三個指針的相對角速度
const double s_h = 719. / 120, s_m = 59. / 10, m_h = 11. /120;
//將角速度換爲週期,即兩指針多長時間後出現一次夾角循環,43200秒即12小時,12小時三個指針重合一次
const double tsh = 43200. / 719, tsm = 3600. / 59, tmh = 43200. / 11;
inline double max(double a, double b, double c)
{
double max = a;
if(b > max)
max = b;
if(c > max)
max = c;
return max;
}
inline double min(double a, double b, double c)
{
double min = a;
if(b < min)
min = b;
if(c < min)
min = c;
return min;
}
int main(int argc, const char *argv[]){
double d;
while(scanf("%lf", &d), d != -1){
double bsm, bsh, bmh, esm, esh, emh, begin, end, total = 0;
//兩兩之間第一次滿足條件的時間
bsm = d / s_m;
bsh = d / s_h;
bmh = d / m_h;
//兩兩之間第一次滿足條件結束的時間
esm = (360 - d) / s_m;
esh = (360 - d) / s_h;
emh = (360 - d) / m_h;
//通過循環找出,三者之間共同的交集,
// |____| |____| |____| |____|
// |____| |____| |____| |____|
// |____| |____| |____| |____|
//因爲CIRCLE爲一個週期,所以滿足範圍必定不會跨越CIRCLE,所以et3 <= CIRCLE合理
for(double bt3 = bsh, et3 = esh; et3 <= CIRCLE; bt3 += tsh, et3 += tsh){
for(double bt2 = bmh, et2 = emh; et2 < CIRCLE; bt2 += tmh, et2 += tmh){
if(et2 < bt3) // et2 |______| //et2還需要增長
continue; // |______| bt3
if(bt2 > et3) // |______| bt2
break; // et3 |______| //bt2再增長也不會有交集了,break
for(double bt1 = bsm, et1 = esm; et2 <= CIRCLE; bt1 += tsm, et1 += tsm){
if(et1 < bt3 || et1 < bt2)
continue;
if(bt1 > et3 || bt1 > et2)
break;
begin = max(bt1, bt2, bt3);
end = min(et1, et2, et3);
total += (end - begin);
}
}
}
printf("%.3lf\n", total / 432);
}
return 0;
}