HFUTOJ problem 1356实现总结

来源:互联网 发布:java免费下载 编辑:程序博客网 时间:2024/06/10 14:33

题目

Description

在二维平面上,有一个固定的圆和一个固定的点(保证该点不在圆上),还有一个动点在圆上以角速度w绕圆心一直转。在t时刻,连接该动点与定点成一条直线k,求直线k被圆所截线段的长度(即直线k在圆内部分长度)。
动点初始时刻在圆的三点钟方向(即与x轴正方向平行),并以逆时针方向绕圆转。

Input

先输入一个整数T,表示T(T<50)组数据。
每组数据一行七个实数a,b,r(r>0),x,y,w(w>=0),t(t>=0) 分别表示圆的圆心坐标(a,b),半径r,固定点坐标(x,y),角速度w,要查询的时刻t。
上述所有数据的绝对值小于10000。

Output

输出答案占一行,保留2位小数。

Sample Input

1
1 1 1 3 1 3 0

Sample Output

2.00

Hint

角速度定义:
一个以弧度为单位的圆(一个圆周为2π,即:360度=2π),在单位时间内所走的弧度即为角速度。

思路

作为一个数学惨不忍睹的人(尤其是几何),看到这种题目真是想死的心都有了(做了之后更想死了)。这题目与其说是一个编程题还不如说是个高中数学题。

如图所示

总的来说,就是求出圆心到直线的距离,然后利用勾股定理,result = (r^2 - d^2)^0.5 * 2。
1. 解题的核心是求出B点的坐标和直线AB的表达式。直接求B点坐标肯定是求不出来的,但是可以换个思路:在圆里,B的坐标相对于圆心的坐标为 (r*cos(w*t), r*sin(w*t)),这样,B在坐标系中的坐标即为(a+r*cos(w*t), b+r*sin(w*t))。
2. 获得B点坐标后,就可以求直线AB的表达式了,由两点式 (x-x1)/(x2-x1)=(y-y1)/(y2-y1) 可得 (y2-y1)*x+(x1-x2)*y + (x2-x1)*y2 + (y1-y2)*x1 = 0,即在标准式中,a = Yb-Ya, b = Xa-Xb, c = (Xb-Xa)*Ya+(Ya-Yb)*Xa。
3. 上述数据算出来之后,就可以计算圆心到直线AB的距离d了,利用点到直线的距离公式|ax+by+c|/(a^2 + b^2)^0.5即可得出d。
4. 没了,计算结果吧。

代码

#include <iostream>#include <cmath>#include <iomanip>using namespace std;int main (void){    int TestTimes = 0, Times = 0;    cin >> TestTimes;    while (Times++ < TestTimes){        double a = 0, b = 0, r = 0, Xa = 0, Ya = 0, w = 0, t = 0;        cin >> a >> b >> r >> Xa >> Ya >> w >> t;        double Xb = a + r*cos(w*t), Yb = b + r*sin(w*t);        double Lab_a = Yb-Ya, Lab_b = Xa-Xb, Lab_c = (Xb-Xa)*Ya+(Ya-Yb)*Xa;        double d = abs(a*Lab_a + b*Lab_b + Lab_c)/sqrt(pow(Lab_a,2) + pow(Lab_b,2));        cout << fixed << setprecision(2) << 2*sqrt(pow(r,2) - pow(d,2)) << endl;    }    return 0;}

需要说明的是,其实在这里完全可以把所有的计算全部放到输出语句中,但是这样会造成程序可读性降低到一个不忍直视的地步,像这样:

cout << fixed << setprecision(2) << 2*sqrt(pow(r,2) - pow(abs(a*(b + r*sin(w*t)-Ya) + b*(Xa-a + r*cos(w*t)) + (Xb-Xa)*Ya+(Ya-b + r*sin(w*t))*Xa)/sqrt(pow(b + r*sin(w*t)-Ya,2) + pow(Xa-b + r*sin(w*t),2)),2)) << endl;

你能看出来这是啥咩。。。。
反正我是看不出来。。。。┑( ̄Д  ̄)┍。

本来做着题目的时候还有很多想吐槽的,想想还是别在这里写了。

0 0