第一次写博客,此文是关于HDOJ 1006题Tick and Tick的学习与整理;自己捣鼓了好几天,看了网上的一些解题思路最后终于琢磨出来,希望对大家有所帮助。
对于该题起初的设想是在12小时内(对称结构)遍历秒指针43200次,而此做法无法达到题目的精度要求,不得不放弃;后面想想确实如此,若按秒为单位由于1秒经过的是6º,从而会有很大的误差。
既然此路不通,原因也很明确(精度不够);便换一条思路,考虑到指针的夹角是关于时、分、秒的线性函数,当时、分确定便可得到关于秒的线性不等式组;所以回退一步遍历12*60分钟,从而计算计算出每一分钟内happyTime的区间范围(还是以秒为单位);最后计算出总的happyTime区间占总的区间大小43200的比例即可。要实现此目标首先便需要计算任一时刻H:M:S(0 <= H < 12, 0 <= M < 60, 0 <= S < 60, H,M皆为整数, S为实数)下各指针相对于0时刻(统一参照点)的夹角,简单分析可得各夹角分别为HAngle = 30 * H + (1/2) * M + (1/120) * S;MAngle = 6 * M + (1/10) * S;SAngle = 6 * S;而happyTime的定义是要求各指针夹角均不小于D,之后只需求解关于S的不等式组:D≤|HAngle - MAngle|≤360 - D ; D≤|HAngle - SAngle|≤360 - D ; D≤|MAngle - SAngle|≤360 - D。所得到的结果保存在数组Seg[3][2]中,最终的结果为(Seg[0][0]∪Seg[0][1])∩(Seg[1][0]∪Seg[1][1])∩(Seg[2][0]∪Seg[2][1])其中对于绝对值的解集Seg[0][0]∩Seg[0][1] = 0(之后求解有用)
既然思路明确,那么此题的关键便是求解不等式组,对于上述六个数组分别用a,b,c,d,e,f代替(为求方便);不等式组的解最终可以转换为
(a∩c∩e)∪(b∩c∩e)∪(a∩d∩e)∪(b∩d∩e)∪(a∩c∩f)∪(b∩c∩f)∪(a∩d∩f)∪(b∩d∩f),且其中(a∩b = c∩d = e∩f = 0),即上述8个不等式互不相交;所有S的解集为:
(a∩c∩e) + (b∩c∩e) + (a∩d∩e) + (b∩d∩e) + (a∩c∩f) + (b∩c∩f) + (a∩d∩f) + (b∩d∩f)
以下是本人AC代码,仅供参考:
#include<iostream>
#include<iomanip>
using namespace std;
//区间结构体
struct Interval
{
double left;
double right;
};
//求解区间1
Interval Solving1(double coef , double constant , double Degree)
{
Interval result;
double _left = (Degree + constant) / coef;
double _right = (360 - Degree + constant) / coef;
if(_left < 0)
_left = 0;
if(_right > 60)
_right = 60;
if(_left > _right)
_left = _right = 0.0;
result.left = _left;
result.right = _right;
return result;
}
//求解区间2
Interval Solving2(double coef , double constant , double Degree)
{
Interval result;
double _left = (Degree + constant - 360) / coef;
double _right = (constant - Degree) / coef;
if(_left < 0)
_left = 0;
if(_right > 60)
_right = 60;
if(_left > _right)
_left = _right = 0.0;
result.left = _left;
result.right = _right;
return result;
}
//求交集
Interval operator * (Interval a , Interval b)
{
Interval result;
if(a.left < b.left)
result.left = b.left;
else
result.left = a.left;
if(a.right < b.right)
result.right = a.right;
else
result.right = b.right;
if(result.left > result.right)
result.left = result.right = 0.0;
return result;
}
int main()
{
double D , coef , cont;
Interval inter[3][2];
while (cin >> D && (D != -1))
{
double sum = 0.0;
for(int H = 0 ; H < 12 ; ++ H)
{
for(int M = 0 ; M < 60 ; ++ M)
{
//求符合条件的区间范围
//时、分指针夹角
coef = 11.0 / 120;
cont = 30.0 * H - 5.5 * M;
inter[0][0] = Solving1(coef , cont , D);
inter[0][1] = Solving2(coef , cont , D);
//时、秒指针夹角
coef = 719.0 / 120;
cont = 30.0 * H + 0.5 * M;
inter[1][0] = Solving1(coef , cont , D);
inter[1][1] = Solving2(coef , cont , D);
//分、秒指针夹角
coef = 5.9;
cont = 6.0 * M;
inter[2][0] = Solving1(coef , cont , D);
inter[2][1] = Solving2(coef , cont , D);
//求交集
for(int i = 0 ; i < 2 ; ++ i)
for(int j = 0 ; j < 2 ; ++ j)
for(int k = 0 ; k < 2 ; ++ k)
{
Interval Seg = inter[0][i] * inter[1][j] * inter[2][k];
sum += (Seg.right - Seg.left);
}
}
}
cout << setiosflags(ios::fixed) << setprecision(3) << sum / 432.0 << endl;
}
system("pause");
return 0;
}
参考文章:http://hi.baidu.com/guoxiangke2008/item/58f27b3233c80cc22e8ec225?qq-pf-to=pcqq.c2c