Lifting the Stone
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6792 Accepted Submission(s): 2829
2 4 5 0 0 5 -5 0 0 -5 4 1 1 11 1 11 11 1 11
0.00 0.00 6.00 6.00
摘录大神博客
地址:http://www.cnblogs.com/jbelial/archive/2011/08/08/2131165.html
1. 1 累加和求重心
设平面上有N 个离散数据点( xi , yi ) ( i = 1, 2, ., n) , 其
多边形重心G( . x1, . y1) 为:
这是求多边形最简单直观的方法。可以直接利用离散数
据点的x, y坐标就能求图形重心。但是缺陷在于没有对离散
数据点所围图形做任何处理和分析,精度不够。
1. 2 算法一:在讲该算法时,先要明白下面几个定理。
定理1 已知三角形△A1A2A3的顶点坐标Ai ( xi , yi ) ( i =1, 2, 3) 。它的重心坐标为:
xg = (x1+x2+x3) / 3 ; yg = (y1+y2+y3) / 3 ;
定理2 已知三角形△A1A2A3的顶点坐标Ai ( xi , yi ) ( i =1, 2, 3) 。该三角形的面积为:
S = ( (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1) ) / 2 ;
△A1A2A3 边界构成逆时针回路时取+ , 顺时针时取 -。
另外在求解的过程中,不需要考虑点的输入顺序是顺时针还是逆时针,相除后就抵消了。
原理:将多边形划分成n个小区域, 每个小区域面积为σi ,重心为Gi ( . xi , . yi ) ,利用求平面薄板重心公式把积分变
成累加和:
由前面所提出的原理和数学定理可以得出求离散数据点所围多边形的一般重心公式:以Ai ( xi , yi ) ( i = 1, 2, ., n) 为顶点的任意N边形A1A2 .An ,将它划 分成N - 2个三角形(如图1) 。每个三角形的重心为Gi ( . xi , . yi ) ,面积为σi。那么多边形的重心坐标G( .x2, .y2) 为:
图1 多边形分解
#include <cstdio>
#include <iostream>
using namespace std;
typedef struct {
int x, y;
}point;
double Area(point p1, point p2, point p3) {
return (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y);
}
int main()
{
int T, N;
scanf("%d", &T);
while (T--) {
scanf("%d", &N);
point p1, p2, p3;
double sumx = 0, sumy = 0, sumarea = 0;
scanf("%d%d%d%d", &p1.x, &p1.y, &p2.x, &p2.y);
for (int i = 2; i < N; i++, p2 = p3) {
scanf("%d%d", &p3.x, &p3.y);
double area = Area(p1, p2, p3);
sumarea += area;
sumx += (p1.x + p2.x + p3.x) * area;
sumy += (p1.y + p2.y + p3.y) * area;
}
sumx = sumx / 3 / sumarea;
sumy = sumy / 3 / sumarea;
printf("%.2f %.2f\n", sumx, sumy);
}
return 0;
}