HDU 1115 (平面几何 重心)

用重心公式 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值