UVA11186题解

题意简述

建立一个极坐标系,在一个圆心在极点,半径为 r 的圆周上有 n 个点,求这些点围成的所有三角形面积之和,对于每个点给出一个 θ,代表这个点的极坐标为 (r,θ)

题目分析

其他题解中的算法时间复杂度为 O(n3),对于题目中 n500 的数据范围足够了,但数据稍有加强就会被卡,在此给出一种时间复杂度为 O(n2) 的算法。

首先我们分析一下圆周上三个点组成的三角形面积该如何求。如图所示,圆内接三角形的面积都可以由圆的面积减去三个弓形(绿色部分)的面积之和来求出。 解释 那么,所有三角形面积之和就是 Cn3×SO 减去每个三角形所对应的三个弓形面积之和。接下来,我们可以将给出的 θ 递增排序,那么对于两个点 ij(假设 i<j),在其之间有 ji1 个点,如图所示,弦 ij 两侧的弓形在所有三角形对应的弓形中分别共被减去 ji1 次与 n+ij1 次。 解释2 那么,对于每个弓形被减的次数已经知道了,只需要再计算出每个弓形的面积即可。对于两个点 ij,以 ij 为弦的扇形(指对应圆心角较小的弓形)面积即为S=(θjθi)×π×r2360\degreer2×sin(θjθi)2,而另一侧面积较大的弓形面积为 π×r2S。另外,需要注意的一点是计算三角函数时为了适应 C++ 的标准,应将输入的角度转换为弧度形式存储,并且这样可以简化最终的答案。

最后给出代码:

#include<bits/stdc++.h>
using namespace std;
const double Pi=2*acos(0);//计算圆周率。
int n,r;
double A[510],ans,th,s;
int main()
{
while(scanf("%d%d",&n,&r)&& n&&r)
{
//为了方便,我将面积在最后才乘的 r*r。
ans=Pi*(n*(n-1)*(n-2)/6);
for(int i=1;i<=n;i++)
scanf("%lf",&A[i]),A[i]=A[i]*Pi/180.0;//转成弧度。
sort(A+1,A+n+1);//角度排序。
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
th=(A[j]-A[i])/2,s=th-cos(th)*sin(th);//th 为圆心角,s为小弓形面积(没乘 r*r)。
ans-=(j-i-1)*(Pi-s)+(n-j+i-1)*s;//减去弓形面积。
}
ans*=r*r;
printf("%.0lf\n",ans);
}
return 0;
}
posted @   Hadtsti  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示