第一次写博客,此文是关于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