首先,欢迎大家来访问我老师的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奆佬讨论了一下发现不容易啊……)