B. Area of the Devil

  • 借这道题夯实一下计算几何的基础
  • 向量积:顺负逆正
  • 两线交点和夹角都是借助向量工具求解的
  • 分类讨论:圆弧小于180度时,减去三角形面积;大于180度时,加上三角形面积
  • 割补法求面积(正难则反)
  • C++中的角度以弧度制表示
#include <bits/stdc++.h>
using namespace std;
const double pi=acos(-1.0);
int s[10],t[10],r;
typedef pair<double,double> pdd;
pdd operator +(pdd a,pdd b)
{
	return {a.first+b.first,a.second+b.second};
}
pdd operator -(pdd a,pdd b)
{
	return {a.first-b.first,a.second-b.second};
}
pdd operator *(double a,pdd b)
{
	return {a*b.first,a*b.second};
}
double operator ^(pdd a,pdd b)
{
	return a.first*b.first+a.second*b.second;
}
double operator *(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+((c-a)*l1)/(l1*l2)*l2;
}
double area(vector<pdd>polygon)
{
	double res=0;
	for(int i=0;i<polygon.size();i++)
	{
		res=res+polygon[i]*polygon[(i+1)%polygon.size()];
	}
	return 0.5*fabs(res);
}
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);
}
int sgn(double x)
{
	return x>0?1:-1;
}
double shu(pdd a,pdd b)
{
	double w1=(a*b);
	double w2=acos((a^b)/len(a)/len(b));
	if(w2<0)
	{
		w2=-w2;
	}
	else if(w2>pi)
	{
		w2=2*pi-w2;
	}
	if(w1<0)
	{
		w2=2*pi-w2;
	}
	return (w2/(2*pi))*pi*r*r-area({a,b,{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()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		cin>>r;
		for(int i=1;i<=5;i++)
		{
			cin>>s[i];
		}
		for(int i=1;i<=5;i++)
		{
			cin>>t[i];
		}
		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-=area({get_dot(s[1]),get_dot(t[5]),tmp});
			ans-=shu(get_dot(t[5]),get_dot(s[1]));
			lunhuan();
		}
		cout<<fixed<<setprecision(9)<<ans<<endl;
	}
	return 0;
}
posted @ 2024-07-10 20:56  D06  阅读(58)  评论(0)    收藏  举报
//雪花飘落效果