您的位置:首页 > 编程语言 > C语言/C++

HFUTOJ problem 1356实现总结

2017-03-12 19:49 155 查看

题目

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;


你能看出来这是啥咩。。。。

反正我是看不出来。。。。┑( ̄Д  ̄)┍。

本来做着题目的时候还有很多想吐槽的,想想还是别在这里写了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ 算法