这道题比较自己看到后比较迷茫,在网上搜了下,发现大部分都是直接给出代码,具体解题思路不容易一下看明白,自己花了些时间,将思路整理了下。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1006
这道题目需要求时针、分针、秒针之间的间隔区间大于某个角度(这个角度由用户输入)的总时间占一天之中总时间的比例。
可以这样理解:
1、我们只需要算出时钟从12点整(3个指针重合),到下一次在12点整(三个指针再次重合)这12个小时的时间过程中,这3个指针之间的区间间隔大于指定角度的时间(即秒数)即可。
2、既然是算秒数,我们可以算这12个小时,也就是在这720分钟当中,每分钟有多少秒这三个指针的位置符合要求。
3、于是,我们就需要计算在h:m:s,即h时m分s秒时刻,这三个指针偏离12点整位置的角度(因为这样便于计算这三个指针的相对角度差,即它们相距的区间):
时针偏离的角度为:hAngle = 30*h + 0.5*m + (1/120)*s
分针偏离的角度为:mAngle = 6*m + 0.1*s
秒针偏离的角度为:sAngle = 6*s
4、接下来,我们计算这三个指针的角速度:
时针的角速度为:hV = 1/120度每秒
分针的角速度为:mV = 0.1度每秒
秒针的角速度为:sV = 6度每秒
5、这样,我们就可以根据上式算出h时m分这一分钟内,有多少秒使这三个指针的位置是符合要求的。
假如用户输入的区间间隔是degree度,位置要求是这样的:1) degree<=|hAngle-mAngle|<=360-degree 2) degree<=|hAngle-sAngle|<=360-degree 3) degree<=|mAngle-sAngle|<=360-degree
所以在这一分钟之内,满足上面三个等式的时间(即秒数),为我们所求。
6、这样我们就能得到3个s的区间,而这个区间必须与[0,60]取交集,因为这是计算的一分钟内的秒数,不可能超过60秒。
7 、对这3个区间求交集,即可得到所需的秒数。
#include <stdio.h>
#define hAngle h*30.0+m*0.5+s/120.0
#define mAngle m*6.0+s*0.1
#define sAngle s*6.0
#define hV 1.0/120
#define mV 0.1
#define sV 6.0
typedef struct{
double l;
double r;
}interval;
double degree;
double s = 0;
interval solveInequality(double vDiff, double angleDiff){
//解不等式:degree<=|vDiff*s+angleDiff|<=360-degree
interval in;
if(vDiff > 0){
in.l = (degree-angleDiff)/vDiff;
in.r = (360-degree-angleDiff)/vDiff;
}
else{
in.l = (360-degree-angleDiff)/vDiff;
in.r = (degree-angleDiff)/vDiff;
}
if(in.l < 0){
in.l = 0;
}
if(in.r > 60){
in.r = 60;
}
if(in.l >= in.r){
in.l = in.r = 0;
}
return in;
}
interval intersection(interval a, interval b){
interval c;
if(a.l > b.l){
c.l = a.l;
}
else{
c.l = b.l;
}
if(a.r < b.r){
c.r = a.r;
}
else{
c.r = b.r;
}
if(c.l >= c.r){
c.l = c.r = 0;
}
return c;
}
double happyTime(int h, int m){
double vDiff, angleDiff;
double result=0;
interval ss[3][2];
interval in;
int i, j, k;
//解不等式degree<=|hAngle-mAngle|<=360-degree
vDiff = hV- mV;
angleDiff = hAngle - mAngle;
ss[0][0] = solveInequality(vDiff, angleDiff);
ss[0][1] = solveInequality(-vDiff, -angleDiff);
//degree<=|hAngle-sAngle|<=360-degree
vDiff = hV- sV;
angleDiff = hAngle - sAngle;
ss[1][0] = solveInequality(vDiff, angleDiff);
ss[1][1] = solveInequality(-vDiff, -angleDiff);
//degree<=|mAngle-sAngle|<=360-degree
vDiff = mV- sV;
angleDiff = mAngle-sAngle;
ss[2][0] = solveInequality(vDiff, angleDiff);
ss[2][1] = solveInequality(-vDiff, -angleDiff);
for(i=0; i<2; i++){//求交集
for(j=0; j<2; j++){
for(k=0; k<2; k++){
in = intersection(intersection(ss[0][i], ss[1][j]),ss[2][k]);
result += (in.r-in.l);
}
}
}
return result;
}
int main(){
int h, m;
double result = 0;
scanf("%lf", °ree);
while(degree != -1){
for(h=0; h<12; h++){
for(m=0; m<60; m++){
result += happyTime(h, m);
}
}
printf("%.3lf\n", result*100.0/43200);
result = 0;
scanf("%lf", °ree);
}
return 0;
}
参考文章: http://blog.csdn.net/gubojun123/article/details/8604163
http://www.cppblog.com/notonlysuccess/archive/2009/03/10/76143.aspx