hdoj-2036题解-向量积法求任意多边形面积

首先看一道hdoj的算法题:hdoj-2036-改革春风吹满地

该题题意就是逆时针给出点的坐标,求这个多边形的面积。下面就写一下如何用向量积法求多边形面积。

向量积法与面积

上图说明了如何利用向量求得三角形的面积,下面介绍一下所谓的右手法则:
如图,2个三角形ABC,唯一的区别在于上面的三角形ABC的标识是逆时针,而下面的三角形标识是顺时针。如果利用向量叉积,由于乘的是向量的绝对值,所以AB与AC在上或者在下是没有区别的。但是如果不使用绝对值,而是写成行列式的形式,就要考虑方向的问题了。所以简单(不负责任)地说,所谓右手法则就是:当逆时针(右手大拇指朝向)方向排列点的时候组成的向量求的的结果是正数,反之是负数。(上面并不是标准解答,关于定义可参考wikipedia)那么以上2个三角形转化为行列式的时候就是下图:
根据行列式的性质,我们也能知道两者的值是相反的。
既然如此,我们在得到逆时针序的3点坐标的情况下,利用行列式即可得到面积。例:
核心代码为:
int S = (0.5)*(x1*y2+x2*y3+x3*y1-x3*y2-x2*y1-x1*y3);

N边形划分为三角形

如上图,任何一个N边形都能划分为N-3个三角形,那么根据上面的公式,我们逆时针获取点,就像下图一样,令单个三角形的面积和累加即可得到N边形的面积。
因为右手定则,一定要逆时针。而该题输入要求就正好是逆时针输入。并且可以看出:A点恒不变,另两个点是移动状态,那么我们就可以写出代码:
int beginx, beginy, lastx, lasty, x, y;
double ans;
cin >> beginx >> beginy >> lastx >> lasty >> x >> y;
ans = (double)(0.5)*(beginx*lasty + lastx*y + x*beginy - x*lasty - lastx*beginy - beginx*y);
以上代码可以得到第一个三角形ABC的面积,下面进入循环:
 
n -= 3;
while (n--) {
	cin >> x >> y;
	ans += (double)(0.5)*(beginx*lasty + lastx*y + x*beginy - x*lasty - lastx*beginy - beginx*y);
	lastx = x;
	lasty = y;
}

最终即可得到解ans。

凹边形面积

我们上面的例子都是凸边形,对于凹边形而言我们仍然可以得到正解,就是因为有右手定则。
如上图的凹边形,我们仍然按照逆时针顺序来求解,第一个三角形ABC,得到实际上是包括虚线在内的整体面积,那么第二个三角形ACD,可以看到是顺时针了,绝对值是有虚线的ACD面积,那么因为是顺时针,用行列式求出的值是负数。两个行列式值相加,正好是大三角形(包括虚线)ABC面积减去小三角形ACD的面积。得到的仍然是凹边形的面积。

C++代码

已AC
#include<iostream>


using namespace std;


int main() {
    int n;
    while (cin >> n) {
        if (n == 0) break;
        int beginx, beginy, lastx, lasty, x, y;
        double ans;
        cin >> beginx >> beginy >> lastx >> lasty >> x >> y;
        ans = (double)(0.5)*(beginx*lasty + lastx*y + x*beginy - x*lasty - lastx*beginy - beginx*y);
        lastx = x;
        lasty = y;
        n -= 3;
        while (n--) {
            cin >> x >> y;
            ans += (double)(0.5)*(beginx*lasty + lastx*y + x*beginy - x*lasty - lastx*beginy - beginx*y);
            lastx = x;
            lasty = y;
        }
        printf("%.1lf\n", ans);
    }


    system("pause");
    return 0;
}

 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值