坐标系切圆湖南训练赛C - Cut the Circle Gym - 323915C

二维坐标平面上有一圆 P , 圆 P 的半径为 r , 且圆心位于坐标原点 . 两条相交线段AB , CD将圆切割为 4 个部分 , 求其中最大部分的面积 .

Input
一行包含 9 个整数 r, xA, yA, xB, yB, xC, yC, xD, yD(1 ≤ r ≤ 5000,  - 5000 ≤ xA, yA, xB, yB, xC, yC, xD, yD ≤ 5000) , 分别表示圆 P 的半径和点 A, B, C, D 的横纵坐标 .

输入保证两条线段 AB 和 CD 的端点都在圆外 , 且其交点严格位于圆 P 的内部 .

Output
输出一行一个浮点数 , 表示答案 . 设输出的答案为 a , 标准答案为 b , 你的答案被认为是正确的 , 当且仅当相对误差小于或等于 10 - 6 , 即 .

Example
Input
1 2 2 -3 -3 -4 4 5 -5
Output
0.7853981634

思路:数学题编成代码

最后错:
//double te=2s/(rr);//不能用正弦!高中就知道一个值有两个解了
//double thra=fabs(asin(te<=1?te:te-2));//这句话没用,不要侥幸,就是错在这,好好想想

苍天有眼C题终于A了,数学麻瓜无疑,正弦定理会有多解
我明明发现不对劲
真是写昏了都不觉得改找错

中间错:
要考虑优弧,
要考虑斜率不存在

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<vector>
#include<map>
#include<set>
#include<ctype.h>
#include<stack>
#include<queue>
#ifdef LOCAL
FILE*FP=freopen("text.in","r",stdin);
//FILE*fp=freopen("text.out","w",stdout);
#endif
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define _forplus(i,a,b) for( register int i=(a); i<=(b); i++)
#define _forsub(i,a,b) for( register int i=(a); i>=(b); i--)
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define INF 0x3f3f3f3f
#define N 100005
const double pi=acos(-1);
struct Poi
{
    double x,y;
    Poi(double x=0,double y=0):x(x),y(y){}
    friend istream&operator>>(istream&input,Poi&p){
    	input>>p.x>>p.y;
    	return input;
	}
};
inline double han(double a11,double a12,double a21,double a22){
	return a11*a22-a12*a21;
}
void get(Poi&m,double a11,double a12,double a21,double a22,double b1,double b2){
	double d=han(a11,a12,a21,a22);
	double d1=han(b1,a12,b2,a22);
	double d2=han(a11,b1,a21,b2);
	m.x=d1/d;
	m.y=d2/d;
}
inline double chu(double a,double b,double c,double d){
	return (a-b)/(c-d);
}
void solve(Poi&A,Poi&B,double a,double b,double c,double k,double b1){
	double deta=b*b-4*a*c;
	A.x=(-b+sqrt(deta))/(2*a);
	B.x=(-b-sqrt(deta))/(2*a);
	A.y=k*A.x+b1;
	B.y=k*B.x+b1;
}
double sq(Poi&a,Poi&b,Poi&c){
	double te=fabs(han(c.x-a.x,c.y-a.y,c.x-b.x,c.y-b.y));
	return fabs(han(c.x-a.x,c.y-a.y,c.x-b.x,c.y-b.y))/2;//三角形面积/2 
}//三角形面积 
inline double d(Poi a,Poi b ){
	return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));
}
double costhra(Poi o,Poi a,Poi b){
	return (pow(d(o,a),2)+pow(d(o,b),2)-pow(d(a,b),2))/(2*d(o,a)*d(o,b));
}
double by(Poi&a,Poi&b,double r,bool l){
	Poi o(0,0);
	double s=sq(o,a,b);
	double thra=acos(costhra(o,a,b));
	//double te=2*s/(r*r);//不能用正弦!高中就知道一个值有两个解了 
	//double thra=fabs(asin(te<=1?te:te-2));//这句话没用,不要侥幸,就是错在这,好好想想 
	return (l?thra:2*pi-thra)*r*r/2-(l?s:-s); 
}//弧面积 
bool bl(Poi a,Poi b,Poi o,Poi m){
	double j1=han(a.x-o.x,a.y-o.y,b.x-o.x,b.y-o.y);
	double j2=han(a.x-m.x,a.y-m.y,b.x-m.x,b.y-m.y);
	if((j1>0&&j2>0)||(j1<0&&j2<0))return true;
	return false;
}//同侧同好true, 
int main(){
	//Poi q(0,1),w(1,0);
	//double res=by(q,w,1,false);
	double r;
	Poi a,b,c,d;
	cin>>r>>a>>b>>c>>d;
	Poi m;
	Poi A,B,C,D;
	double chu1=chu(a.y,b.y,a.x,b.x),chu2=chu(c.y,d.y,c.x,d.x);
	double b1=-chu1*b.x+b.y,b2=-chu2*d.x+d.y;
	if(fabs(chu1)>INF){
		m.x=a.x;
		m.y=chu2*m.x+b2;
		goto here;
	}else if(fabs(chu2)>INF){
		m.x=c.x;
		m.y=chu1*m.x+b1;
		goto here;
	}
	get(m,chu1,-1,chu2,-1,-b1,-b2);
here:
	if(fabs(chu1)>INF){
		A.x=B.x=m.x;
		A.y=sqrt(r*r-A.x*A.x);
		B.y=-sqrt(r*r-B.x*B.x);
	}else solve(A,B,1+chu1*chu1,2*b1*chu1,b1*b1-r*r,chu1,b1);
	if(fabs(chu2)>INF){
		C.x=D.x=m.x;
		C.y=sqrt(r*r-C.x*C.x);
		D.y=-sqrt(r*r-D.x*D.x);
	}else solve(C,D,1+chu2*chu2,2*b2*chu2,b2*b2-r*r,chu2,b2);

	double s[6];
	Poi o(0,0);
	s[1]=sq(m,A,C)+by(A,C,r,bl(A,C,o,m));//若m在线外,要减 
	s[2]=sq(m,A,D)+by(A,D,r,bl(A,D,o,m));
	s[3]=sq(m,B,C)+by(B,C,r,bl(B,C,o,m));
	s[4]=sq(m,B,D)+by(B,D,r,bl(B,D,o,m));
	sort(s+1,s+5);
	printf("%.10f\n",s[4]);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值