uva10002 Center of Masses

题意:计算多边形的重心

解题:先找出凸包,再计算凸多边形重心

WA:数据类型

代码:

 

//uva10002 Center of Masses
//AC By Warteac
//Runtime:0.352s
//2013-5-17
/*
    点的类型:double
    凸包:按极角排序,极角相同的按照距离最左下点的距离从小到大排序
         结果:只输出顶点,不输出边上的点
    WA: 输入数据没有确定范围,PType的类型是int型时WA,把PType改为double型就可以AC
        原因:可能是数据太大,(题目没有明显给出数据范围)叉积已经超出范围了> <!
*/
#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include <iomanip>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double PType;//定义点的类型
typedef double CType;//定义重心点的类型
const double eps = 1e-20;
///
struct Point{
    PType x,y;
    Point(PType a = 0, PType b = 0){x  = a; y = b;}
    void print(){cout << x << " " << y << endl;} 
    Point operator -(Point p){return Point(x - p.x, y - p.y);} 
}pBase;//最左下的点
struct center{
   CType x,y;
   center(CType a = 0, CType b = 0){x = a; y = b;}
   void print(){cout << x << " " << y << endl;}
};
typedef Point Vector;//向量
double direction(Vector v1,Vector v2){//求两个向量的叉积
 	return (v1.x*v2.y-v1.y*v2.x);
 }
bool cmp(Point p1, Point p2){//比较函数
    double d = direction(p1 - pBase, p2 - pBase);
    if(fabs(d) < eps){//极角相同
        return fabs(p1.x) < fabs(p2.x);//距原点的距离从小到大排
    }else {
        return d < eps;//按逆时针排序
    }
}
bool grham_scan(vector <Point> p , vector <Point> &parray){//求凸包的算法
//find first point p0 with minimum y-coordinate or minimun x-coordinate if y are the same
    int index = 0;
    for(int i = 1; i < p.size(); i++){
        if(p[i].y < p[index].y ||(p[i].y == p[index].y && p[i].x < p[index].x))
            index = i;
    }
    swap(p[0],p[index]);
    pBase = p[0];
    sort(p.begin()+1,p.end(),cmp);
//for(int i = 0; i < p.size(); i++){
//    p[i].print();
//}
//cout << endl;
//get the convex hull from p
    parray.clear();
    parray.push_back(p[0]);
    parray.push_back(p[1]);
    p.push_back(p[0]);
    for(int i = 2; i < p.size(); i++){
       Vector v1 (p[i].x - parray.back().x, p[i].y - parray.back().y);
       Vector v2 (parray.back().x - (parray.end()-2)->x, parray.back().y - (parray.end()-2)->y);
       double d = direction(v2,v1);
       if(d < eps) {parray.push_back(p[i]);}
       else if(d >= eps){ //Modify
       parray.pop_back();i--; 
       }
    }   
    return true;
}
center centerPoint(vector <Point> v){
    double sumArea = 0;
    double keciArea = 0;
    double nx = 0,ny = 0;
    for(int i = 1; i < v.size()-1; i++){
        keciArea = direction(v[i+1] - pBase, v[i] - pBase) * 0.5;
        sumArea += keciArea;
        nx += (pBase.x + v[i].x + v[i+1].x)*keciArea;
        ny += (pBase.y + v[i].y + v[i+1].y)*keciArea;
    }
    return center(nx/(3.0*sumArea),ny/(3.0*sumArea));
}
//
int main(){
    int sites;
    PType x,y;
    vector <Point> v;
    Point t,mi;
    while(cin >> sites && sites >= 3){
        v.clear();
        vector <Point> temp;//one convex hull
        while(sites--){
	        cin >> t.x >> t.y;
	        v.push_back(t);
        }
	    if(grham_scan(v,temp) == true){
	    //temp.pop_back();//去掉重复的最后一个点(头点)
//for(int i = 0; i < temp.size(); i++){
//    temp[i].print();
//}	    
//cout << endl;            
	        center c = centerPoint(temp);
	        cout << setiosflags(ios::fixed) << setprecision(3);
	        c.print();
	    }else{
	        cout << "no convex hull" << endl;
	    }
     }
 return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值