题目如下:
在某个多边形上,取n个点,这n个点顺序给出,按照给出顺序将相邻的点用直线连接, (第一个和最后一个连接),所有线段不和其他线段相交,但是可以重合,可得到一个多边形或一条线段或一个多边形和一个线段的连接后的图形;
如果是一条线段,我们定义面积为0,重心坐标为(0,0).现在求给出的点集组成的图形的面积和重心横纵坐标的和;
1.点是顺序给出,并按照顺序连接。
2.线段可以重合但是不相交。
回顾一下高中的知识:
向量:指具有大小和方向的量,对应的是标量(指只有大小,没有方向的量)
长度为0的向量叫零向量,记作长度等于1单位的向量叫单位向量。
平行向量:方向相同或相反的非零向量。
规定:零向量与任意向量都是平行向量。
向量的加减法的平行四边形法则和三角形法则。
向量的乘法:数乘 λ · a 结果还是向量, 1方向:当λ > 0, λa 与a同向。 λ< 0 , λa与a反向。λ =0,λa方向任意。2大小:|λa| = |λ|· |a| 实数的模也是实数的绝对值。
平面向量基本定理: 如果两个向量a,b不共线,那么向量p与向量a、b共面的充要条件是:存在唯一实数对 x、y, 使得 p = xa + yb。此定理主要作用就是说明平面向量的分解和合成。 为向量的坐标表示提供理论依据。
点积:结果是实数
数量积也称为点积、点乘;是接受在实数R上的两个向量并返回一个实数值标量的二元运算。 两个向量 a = [a1, a2, .... , an] 和 b = [b1, b2, ... , bn]的点积 定义为:a·b = a1b1 + a2b2 + ... + anbn。 运算式: a·b = |a||b| · cosθ
叉积:结果是向量
向量积,是一种在向量空间中向量的二元运算,与点积不同,它的运算结果是一个向量而不是一个标量,并且两个向量的叉积与这两个向量和垂直。 运算式: a×b=c, 其中|c|=|a||b|·sinθ, c的方向遵守右手定则
注:向量积 ≠向量的积(向量的积一般指点乘)
坐标计算多边形面积公式:(注意,构成闭合的多边形的边不能有交叉,如果闭合多边形存在交叉边线段,则应沿交叉点分开成单独的闭合多边形,再求面积之和。)
向量a.b的叉积的模可以解释成以向量a和b为邻边的平行四边形面积。
所以多边形的面积就是求相邻的两个点的三角形面积和的二分之一,即相邻两个点的叉积和的二分之一。
多边形的重心如何求解,如果一个三角形的坐标为
则它的重心坐标为:
同理,多边形的重心可以通过分解成三角形重心公式求得。
即把三角形面积(叉积)*重心坐标(x,y)累加和除以总面积得到多边形的重心坐标。不用关心正负。除操作后符号被消除。
#ifndef _ACM_C_
#define _ACM_C_
#include <math.h>
#include <stdio.h>
typedef unsigned int uint16_t;
//计算三角形面积
double CalArea(double point1[2], double point2[2]) {
return (point1[0] * point2[1] - point1[1] * point2[0]) / 2.0;
}
int main(int argc, char** argv) {
uint16_t nTimes = 0;
scanf("%d", &nTimes);
while (nTimes--) {
//点的个数
uint16_t uNum = 0;
scanf("%d", &uNum);
double PointInfo[10000][2] = {0};
double tempX, tempY;
for (int i = 0; i < uNum; ++i)
scanf("%lf %lf", &PointInfo[i][0], &PointInfo[i][1]);
double Barycenter = 0.0, sAreaTotal = 0.0, sTempArea = 0.0;
for (int nIndex = 0; nIndex < uNum; ++nIndex) {
sTempArea = CalArea(PointInfo[nIndex], PointInfo[(nIndex + 1)%uNum]); //点的首位相接,循环;
sAreaTotal += sTempArea;
//获取多边形分解三角形重心累加和
Barycenter += sTempArea * (PointInfo[nIndex][0] + PointInfo[(nIndex + 1) % uNum][0] + PointInfo[nIndex][1] + PointInfo[(nIndex + 1) % uNum][1]) / 3.0;
}
if (fabs(sAreaTotal)<1e-7)
printf("0.000 0.000\n");
else
printf("%.3lf %.3lf\n", fabs(sAreaTotal), Barycenter / sAreaTotal); //不用考虑正负
}
return 0;
}
#endif