Description
农夫有一个长满草的(x0, y0)为圆心,r为半径的圆形牛栏,他要将一头牛栓在坐标(x1, y1)栏桩上,但只让牛吃到一半草,问栓牛鼻的绳子应为多长?
Input
输入一个T,表示T组测试数据
下面T行每行五个整数 x0, y0, x1, y1, r 所有数据的绝对值小于1e5
Output
每组测试数据输出绳子长度,保留4位小数
Sample Input
2 0 0 0 0 2 0 0 10 10 2
Sample Output
1.4142 14.1892
【思路】
while(rt-lt>eps)二分法,无限逼近
#include<iostream> #include<string.h> #include<math.h> #include<stdio.h> using namespace std; const double pi=acos(-1.0); const double eps=1e-8; double get_s(double mid,int r,int d,double a,double b)//计算面积 { return mid*mid*a-mid*mid*sin(a)+r*r*b-r*r*sin(b); } int main() { int t; scanf("%d",&t); while(t--) { double x0,y0,x1,y1,r; scanf("%lf%lf%lf%lf%lf",&x0,&y0,&x1,&y1,&r); double d=sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)); double lt=d,rt=sqrt((d*d)+(r*r)); if(d+r/(sqrt(2))-r<eps)//如果两个圆心重合,则满足所求R=r/sqrt(2); { printf("%.4f ",1.0*r/sqrt(2)); continue; } double s=pi*r*r; double mid=0.0; while(rt-lt>eps)//二分 { mid=(lt+rt)/2.0; double a=2*acos(((mid*mid)+(d*d)-(r*r))/(2.0*mid*d));//求圆心角a double b=2*acos(((d*d)+(r*r)-(mid*mid))/(2.0*d*r));//求圆心角b double ss= get_s(mid,r,d,a,b); if(ss-s>eps) rt=mid-eps; else lt=mid+eps; } printf("%.4f ",mid); } return 0; }