题目链接 http://lightoj.com/volume_showproblem.php?problem=1433
题意: 求劣弧弧长
思路: 先算角度再算弧长。虽然题目中说精度到小数点后3位就行,但测试数据很强,尽量少开方。
这题比 LightOJ 1130 好算多了……
#include <stdio.h>
#include <math.h>
const double PI=acos(-1.0);
const double STD=1e-9;
struct Point
{
double x,y;
Point friend Vec (Point a,Point b) //构造向量
{
Point res;
res.x=a.x-b.x;
res.y=a.y-b.y;
return res;
}
}cir,a,b;
double get_cj (Point a,Point b) //计算叉积
{
return a.x*b.y-a.y*b.x;
}
double get_dj(Point a,Point b) //计算点积
{
return a.x*b.x+a.y*b.y;
}
double get_dis (Point a,Point b) //计算两点间距离
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double get_dis2 (Point a,Point b) //计算两点间距离的平方
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
double Deal ()
{
scanf("%lf%lf%lf%lf%lf%lf",&cir.x,&cir.y,&a.x,&a.y,&b.x,&b.y);
if (fabs(a.x-b.x)< STD && fabs(a.y-b.y)<STD)
return 0;
double da=get_dis2 (a,cir);
double db=get_dis2 (b,cir);
double cj=get_cj (Vec(a,cir),Vec(b,cir));
double dj=get_dj (Vec(a,cir),Vec(b,cir));
double dsin=cj/sqrt(da*db); //da,db是平方过的,先开方再乘WA……
double alpha=asin(dsin);
if (dj < 0) //当夹角大于90度时
if (alpha>0)
alpha=PI-alpha;
else
alpha=-PI-alpha;
return get_dis (a,cir)*fabs(alpha);
}
int main ()
{
int T;
scanf("%d",&T);
for (int cas=1;cas<=T;cas++)
printf("Case %d: %.6lf\n",cas,Deal());
return 0;
}
/*
5
1 1 1 1 1 1
10 10 9 10 11 10
10000 10000 9000 10000 10000 9000
10000 10000 10000 9000 9000 10000
1 1 101 1 1 101
Output
Case 1: 0.00000000
Case 2: 3.14159265
Case 3: 1570.79632679
Case 4: 1570.79632679
Case 5: 157.07963268
*/