B. Area of the Devil

  • 借这道题夯实一下计算几何的基础
  • 向量积:顺负逆正
  • 两线交点和夹角都是借助向量工具求解的
  • 分类讨论:圆弧小于180度时,减去三角形面积;大于180度时,加上三角形面积
  • 割补法求面积(正难则反)
  • C++中的角度以弧度制表示
点击查看代码
#include <bits/stdc++.h>
#define pdd pair<double,double>
using namespace std;
const double pi=acos(-1.0);
int s[10],t[10],r;
pdd operator -(pdd a,pdd b)
{
	pdd c;
	c.first=a.first-b.first;
	c.second=a.second-b.second;
	return c;
}
pdd operator +(pdd a,pdd b)
{
	pdd c;
	c.first=a.first+b.first;
	c.second=a.second+b.second;
	return c;
}
pdd operator *(double a,pdd b)
{
	pdd c;
	c.first=b.first*a;
	c.second=b.second*a;
	return c;
}
pdd get_dot(int rad)
{
	return make_pair(cos(rad*pi/180.0)*r,sin(rad*pi/180.0)*r);
}
double len(pdd a)
{
	return sqrt(a.first*a.first+a.second*a.second);
}
double mul1(pdd a,pdd b)
{
	return a.first*b.first+a.second*b.second;
}
double mul2(pdd a,pdd b)
{
	return a.first*b.second-a.second*b.first;
}
pdd jiaodian(pdd a,pdd b,pdd c,pdd d)
{
	pdd l1=b-a,l2=d-c;
	return c+mul2(c-a,l1)/mul2(l1,l2)*l2;
}
double stri(pdd a,pdd b,pdd c)
{
	pdd l1=b-a,l2=c-a;
	return fabs(0.5*mul2(l1,l2));
}
int sgn(double x)
{
	if(x>0)
	{
		return 1;
	}
	return -1;
}
double shu(pdd a,pdd b)
{
	double w1=mul2(a,b);
	double w2=(acos(mul1(a,b)/len(a)/len(b)));
	if(w1<0)
	{
		w2=2*pi-w2;
	}
	return (w2/(2*pi))*pi*r*r-stri(a,b,make_pair(0,0))*sgn(w1);
}
void lunhuan()
{
	for(int i=1;i<=5;i++)
	{
		s[i-1]=s[i];
		t[i-1]=t[i];
	}
	s[5]=s[0];
	t[5]=t[0];
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		r=read1();
		for(int i=1;i<=5;i++)
		{
			s[i]=read1();
		}
		for(int i=1;i<=5;i++)
		{
			t[i]=read1();
		}
		double ans=pi*r*r;
		for(int i=1;i<=5;i++)
		{
			pdd tmp=jiaodian(get_dot(s[1]),get_dot(t[4]),get_dot(s[2]),get_dot(t[5]));
			ans-=stri(get_dot(s[1]),get_dot(t[5]),tmp);
			ans-=shu(get_dot(t[5]),get_dot(s[1]));
			lunhuan();
		}
		printf("%.9f\n",ans);
	}
	return 0;
}
posted @ 2024-07-10 20:56  D06  阅读(29)  评论(0编辑  收藏  举报