首先,欢迎大家来访问我老师的OJ:小白菜OJ
你是新入门OI的小白吗?
你正在苦于网上的资料不足吗?
你正在因各种blog写得不清不楚、艰涩难懂、千篇一律、满篇术语像LB一样而烦恼吗?
欢迎来到小白菜OJ!
这里有最易懂的视频讲解、基于HustOJ和阿里云的稳定、先进OJ
并且——完全免费!
小白菜OJ——信息学竞赛在线自学系统(caioj.cn)
专业黑LB
好了说正事:我们这篇blog来讲一讲如何用叉积求一个(非自相交)多边形的面积
题面传送门(需要注册账号)
首先,众所周知叉积的大小是两个向量围成的平行四边形的面积
那么,我们把这个大小除以二不就是两个向量围成的三角形的面积了吗?
好的那么我们会求三角形的面积了。
求多边形的面积(非自相交,无论凸凹)就可以转化为求几个三角形的面积。
具体如下:
我们有一个多边形:
这个11边形表现为一个点的数组
a
a
a,而
a
1
a_1
a1就是那个黑点
然后我们从第三个点开始,挨个求它与上一个点、
a
1
a_1
a1围成的三角形面积——也就是求叉积的一半——然后加起来。
注意!这里的面积其实不是指真正的面积,是要包括原来叉积的正负性的!
上图:
先加上
S
△
A
B
C
S_{\triangle ABC}
S△ABC
再加上
S
△
A
C
D
S_{\triangle ACD}
S△ACD
但是,此时,眼尖的同学可能会发现,
F
F
F点上面有一片本来没有的区域被覆盖了!
没关系我们继续看:
加上 S △ A D E S_{\triangle ADE} S△ADE
更明显了呢……
但是!
接下来我们要减去
S
△
A
E
F
S_{\triangle AEF}
S△AEF!
减去
S
△
A
E
F
S_{\triangle AEF}
S△AEF后……
(图中被框起的一部分被删去)
好像解决了呢!
再来:
最终结果就是所有有颜色的部分减去天蓝色圈起来的部分
自己理解一下就好……正确性不会证明了
三角形的面积用叉积来求
然而代码也不难
上代码:
#include<cstdio>
using namespace std;
struct point
{
int x,y;
point operator -(point b)
{return (point){x-b.x,y-b.y};}
}a[1100];
int cp(point a,point b,point o)
{
a=a-o;b=b-o;
return a.x*b.y-b.x*a.y;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].x,&a[i].y);
int ans=0;
for(int i=3;i<=n;i++)
ans+=cp(a[i-1],a[i],a[1]);//核心代码
printf(ans&1?"%d.5000":"%d.0000",ans>>1);//如果除以二有余数,就输出x.5000,不然就输出x.0000
return 0;
}
然而,面对有自相交的情况时,这个东西就不管用了……
所以我有时间时再打一篇blog来探究这个问题(今天跟LZY奆佬讨论了一下发现不容易啊……)