用重心公式 x0 = Σ(xi*mi)/m, y0 = Σ(yi*mi)/m,其中mi用有向三角形的面积表示,也就是叉积的一半。
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
typedef unsigned long long ll;
#define maxn 111
const double eps = 1e-10;
int dcmp (double x) {//控制精度
if (fabs (x) < eps)
return 0;
else return x < 0 ? -1 : 1;
}
#define pi acos(-1)
//***********点,向量
struct point {
double x, y;
point (double _x = 0, double _y = 0) : x(_x), y(_y) {}
point operator - (const point a) const {//向量相减
return point (x-a.x, y-a.y);
}
point operator + (const point a) const {//向量相加
return point (x+a.x, y+a.y);
}
bool operator < (const point &a) const {
return x < a.x || (dcmp (x - a.x) == 0 && y < a.y);
}
bool operator == (const point &a) const {//判断两个点相等
return dcmp (x-a.x) == 0 && dcmp (y-a.y) == 0;
}
point operator * (const double &a) {//向量乘一个数
return point (a*x, a*y);
}
point operator / (const double &b) {//向量除一个数
return point (x/b, y/b);
}
};
double rad_degree (double rad) {//弧度转化为角度
return rad/pi*180;
}
double degree_rad (double degree) {//角度转化为弧度
return degree/180*pi;
}
double cross (point a, point b) {//叉积
return a.x*b.y-a.y*b.x;
}
double dot (point a, point b) {//点积
return a.x*b.x + a.y*b.y;
}
double length (point a) {//向量的模
return sqrt (dot (a, a));
}
double angle (point a, point b) {//两个向量的夹角
return acos (dot (a, b) / length (a) / length (b));
}
point rotate (point a, double rad) {//向量旋转rad角(弧度制)
return point (a.x*cos (rad)-a.y*sin (rad), a.x*sin (rad)+a.y*cos (rad));
}
point nomal (point a) {//单位法向量
//如果是零向量 就返回零向量
if (dcmp (a.x) == 0 && dcmp (a.y) == 0) {
return point (0, 0);
}
double l = length (a);
return point (-a.y/l, a.x/l);
}
point GetLineIntersection (point p, point v, point q, point w) {//获取直线交点
//直线A上的点 直线A的方向向量 直线B上的点 直线B的方向向量
//使用前判断两直线有唯一焦点 当且仅当 corss(v, w)!=0
point u = p-q;
double t = cross (w, u) / cross (v, w);
return p+v*t;
}
double DistanceToLine (point p, point a, point b) {//点到直线的距离
//点p到直线ab的距离
point v1 = b-a, v2 = p-a;
return fabs (cross (v1, v2) / length (v1));
//不加绝对值得到的是有向距离
}
double DistanceToRay (point p, point a, point b) {//点到射线的距离
//点p到射线a,a是射线的端点,b是射线的方向向量
point v = a-p;
if (dot (v, b) >= 0) return length (v);
else return DistanceToLine (p, a, b);
}
double DistanceToSegment (point p, point a, point b) {//点到线段的距离
//点p到线段ab的距离
point v1 = b-a, v2 = p-a, v3 = p-b;
if (dcmp (dot (v1, v2)) < 0) return length (v2);
else if (dcmp (dot (v1, v3)) > 0) return length (v3);
else return fabs (cross (v1, v2)) / length (v1);
}
point GetLineProjection (point p, point a, point b) {//点在直线上的投影
//点p在直线ab上的投影点
point v = b-a;
return a + v*(dot (v, p-a) / dot (v, v));
}
bool SegmentProperIntersection (point a1, point a2, point b1, point b2) {
//判断线段规范相交(交点不在端点)
double c1 = cross (a2-a1, b1-a1), c2 = cross (a2-a1, b2-a1),
c3 = cross (b2-b1, a1-b1), c4 = cross (b2-b1, a2-b1);
return dcmp (c1) * dcmp (c2) < 0 && dcmp (c3)*dcmp (c4) < 0;
}
bool PointOnSegment (point p, point a1, point a2) {//判断点p是不是在线段a1a2上
if (dcmp (cross (a1-p, a2-p)) == 0 && dcmp (dot (a1-p, a2-p)) <= 0)
// 改成小于号表示交点不在端点上
return 1;
return 0;
}
bool SegmentIntersection (point a1, point a2, point b1, point b2) {//判断线段有交点
if (PointOnSegment (a1, b1, b2) || PointOnSegment (a2, b1, b2) ||
PointOnSegment (b1, a1, a2) || PointOnSegment (b2, a1, a2))
return 1;
if (SegmentProperIntersection (a1, a2, b1, b2))
return 1;
return 0;
}
double PolygonArea (point *p, int n) {//多边形的有向面积,加上绝对值就是面积
//n个点
double area = 0;
for (int i = 1; i < n-1; i++) {
area += cross (p[i]-p[0], p[i+1]-p[0]);
}
return area/2;
}
bool PointInPolygon (point a, point *b, int n) {//判断点在多边内部(凸凹都可以)
//点a 多边形数组b 多边形n个点
int w = 0;
for (int i = 0; i < n; i++) {
if (PointOnSegment (a, b[i], b[(i+1)%n]))
return 0;
int k = dcmp (cross (b[(i+1)%n]-b[i], a-b[i]));
int d1 = dcmp (b[i].y - a.y);
int d2 = dcmp (b[(i+1)%n].y - a.y);
if (k > 0 && d1 <= 0 && d2 > 0)
w++;
if (k < 0 && d2 <= 0 && d1 > 0)
w--;
}
if (w != 0)
return 1;
return 0;
}
point centre_of_gravity (point *p, int n) {//多边形的重心(凹凸都可以)
double sum = 0.0, sumx = 0, sumy = 0;
point p1 = p[0], p2 = p[1], p3;
for (int i = 2; i <= n-1; i++) {
//scanf ("%lf%lf", &p3.x, &p3.y);
p3 = p[i];
double area = cross (p2-p1, p3-p2)/2.0;
sum += area;
sumx += (p1.x+p2.x+p3.x)*area;
sumy += (p1.y+p2.y+p3.y)*area;
p2 = p3;
}
return point (sumx/(3.0*sum), sumy/(3.0*sum));
}
point p[1111111];
int n;
int main () {
int t;
cin >> t;
while (t--) {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> p[i].x >> p[i].y;
}
point ans = centre_of_gravity (p, n);
printf ("%.2f %.2f\n", ans.x+eps, ans.y+eps);
}
return 0;
}