其实求多边形面积有许多的方法,这里介绍一个计算几何的方法,比较神奇,只有O(n)的复杂度。
说道计算几何中的神奇方法,就不得不说到向量(又叫矢量,不过这个名词有歧义)。
向量(大佬跳过)
其实,像这种概念问题,大家都可以去问一下我度娘,还挺详细的。
简介
数学中的向量只有两个值,一个方向,一个大小,于是不论怎么平移,它不会有任何改变。不过,这样子表示向量的话,它的用处就太小了。但是,当我们让向量都从一点出发的话,它的意义就很多了,能够做一些奇奇怪怪的事情。所以在计算机算法里,其中有这样一个表示向量的方法:一般都默认一个向量是从原点出发的,把它另一个端点的坐标记下来。
向量有几个基本运算:加、减、点积、叉积。关于其数学计算方法(计算机中次要)以及几何意义(非常重要),大家请自行去百度吧。
接下来会简单介绍一下以上述记录向量的方法进行基本运算
加减法
加减其实特简单,了解一下基本性质之后(或者百度向量后,看一下加减法的图示,这里就懒一点,不搬运了),特别好推,绝对秒出公式。
点积
两个向量的叉积只会返回一个值,而不是一个向量。其几何意义差不多是下面这样 ,有一个向量 a ⃗ \vec{a} a 为BC,还有一个向量 b ⃗ \vec{b} b为BC。那么, a ⃗ \vec{a} a与点积 b ⃗ \vec{b} b为 S Δ A B C D S\Delta ABCD SΔABCD ,就是 A x ⋅ B y − A y ⋅ B x Ax\cdot By-Ay\cdot Bx Ax⋅By−Ay⋅Bx,(注意,不符合交换律)
叉积
叉积返回值是一个向量,大小为点积,方向符合右手螺旋定理,垂直于另外两向量,也就是说叉积运算是三维中的概念(不符合交换律)
计算面积
思路
比如下面这个:
相信一些眼尖的读者已经发现了,这个多边形上的点都连了一条到原点的线段,相邻两点间的连线与两点和原点的连线构成了8个三角形(多边形共八条线段),如果把其中一些三角形的面积加起来,再减掉另一些三角形的面积,就是所求多边形的面积!而且与原点位置什么都无关!
所以我们只要判断哪些三角形加上,哪些三角形减去即可!至于怎么判断,相信我,向量会自动帮你做这件事。
下面上代码
代码
先上个C++的吧
//输入必须是将点按顺序输入,顺时还是逆时程序会处理的
#include<cstdio>
using namespace std;
double ans;
int n;
struct Point{
int x,y;
}a[1000000];
int read(){
int ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
int main(){
n=read();//共n个点
for(int i=1;i<=n;i++) a[i]=(Point){read(),read()};
for(int i=2;i<=n;i++)
ans+=(double)(a[i].x*a[i-1].y-a[i].y*a[i-1].x)/*记得求平行四边形面积公式吗*//2.0;
//求三角形面积。全加起来就好了,因为...面积有方向(正负性),自己会消掉的
ans+=(double)(a[1].x*a[n].y-a[1].y*a[n].x)/2.0;//第1和第n个点单独处理
if(ans<0.0) ans=-ans;//顺时针与逆时针输入结果互为相反数
printf("%lf",ans);
return 0;
}
好长时间没写Python了,几乎忘光了,没事干就写了一个Python版的代码(可能非常啰嗦),就不挂注释了。
x=[1]
y=[1]
ans=0
n=0
n=input()
for i in range(1,n+1):
x.append(0)
y.append(0)
x[i],y[i] = [int(j) for j in raw_input().split()]
for i in range(2,n+1):
ans=ans+(float)(x[i]*y[i-1]-x[i-1]*y[i])/2.0
ans=ans+(float)(x[1]*y[n]-x[n]*y[1])/2.0
if ans<0:
ans=-ans
print ans