题解:UVA11186 正多边形 Circum Triangle
题意简述
给你一个圆的半径 和圆上的 个点,然后任意选择三个点,会组成一个三角形。要输出所有符合要求的三角形面积之和。
思路
注意到是在圆上,因此任选三个点一定能组成三角形。
因为 ,所以考虑暴力枚举。
首先需要将极坐标转化为平面直角坐标,设极坐标下圆半径为 ,给定的角为 ,平面直角坐标下横坐标为 ,纵坐标为 。则:
这个其实蛮好证明的:

根据三角函数的定义,可得 和 两个式子。
移项即可得到上面的式子。
现在的问题在于如何快速计算任意三角形面积。
我们可以采用下面的方法:
- 。
优点:只有乘法。
缺点: 和 难求。
- 。
缺点: 难求。
- ,其中 。
优点:三边使用两点距离公式 即可求。
缺点:因为要多次根号,所以常数特大,在 时过不去。
- 向量叉积法
向量积可以被定义为:
模长:(在这里 表示两向量之间的夹角(共起点的前提下),它位于这两个矢量所定义的平面上,。)
方向: 与 的向量积的方向与这两个向量所在平面垂直,且遵守右手定则。(一个简单的确定满足“右手定则”的结果向量的方向的方法是这样的:若坐标系是满足右手定则的,当右手的四指从 以不超过180度的转角转向 时,竖起的大拇指指向是 的方向。)(以上文段摘自百度百科)
观察法 的公式,不难注意到上面叉积的模长就是三角形面积的两倍。
但是我们如何快速求出叉积的模长呢?
下面是向量叉积的行列式定义(三维空间):
若 且 ,则
不难发现,因为这张图是二维空间,所以 和 都是 。
三个向量 都是单位向量。
把它用行列式展开,得:
显然 和 是 ,所以前两项就不用管了。
是单位向量,所以它的模长是 。
所以 。
这样我们就能快速求了。
代码
#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1);
int n;
double r;
struct node{
double x,y;
}a[505];
node operator -(node a,node b) {
return (node){a.x-b.x,a.y-b.y};
}
const double eps=0.00000001;
//double X(double a,double b,double c,double d){
// return a*d-b*c;
//}
//double S(node x,node y,node z){
// return fabs(X(y.x-x.x,y.y-x.y,z.x-x.x,z.y-x.y));
//}
double Xx(node xx,node yy){
return xx.x*yy.y-xx.y*yy.x;
}
double Sx(node xx,node yy,node zz){
return fabs(Xx(yy-xx,zz-xx));
}
int main(){
while(1){
cin>>n>>r;
if(n==0&&abs(r)<=eps)break;
for(int i=1;i<=n;i++){
double q;
cin>>q;
q=q*1.0/180*pi;
a[i].x=cos(q)*r;
a[i].y=sin(q)*r;
}
double ans=0;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
for(int k=j+1;k<=n;k++){
ans+=Sx(a[i],a[j],a[k]);
}
}
}
printf("%.0lf\n",ans/2);
}
return 0;
}

浙公网安备 33010602011771号