多边形重心问题

多边形重心问题

时间限制: 3000 ms  |  内存限制: 65535 KB
难度: 5
描述
在某个多边形上,取n个点,这n个点顺序给出,按照给出顺序将相邻的点用直线连接, (第一个和最后一个连接),所有线段不和其他线段相交,但是可以重合,可得到一个多边形或一条线段或一个多边形和一个线段的连接后的图形; 
如果是一条线段,我们定义面积为0,重心坐标为(0,0).现在求给出的点集组成的图形的面积和重心横纵坐标的和;
输入
第一行有一个整数0<n<11,表示有n组数据;
每组数据第一行有一个整数m<10000,表示有这个多边形有m个顶点;
输出
输出每个多边形的面积、重心横纵坐标的和,小数点后保留三位;
样例输入
3
3
0 1
0 2
0 3
3
1 1
0 0
0 1
4
1 1
0 0
0 0.5
0 1
样例输出
0.000 0.000
0.500 1.000
0.500 1.000
思路:将多变形分割成三角形再进行计算。
参考资料:三角形面积:点击打开链接
多边形重心:点击打开链接
结果位数保留:点击打开链接
代码一(原创)如下:
#include<iostream>
#include<cmath>
#include<iomanip>
using namespace std;
int n,m;
double *price;
void cal(){
	//求取横坐标 	
	double area=0.0,x=0.0,y=0.0;
	for(int i=0;i<(m-2);i++){
		//分割成三角形求取面积
		double temp=0.0;
		double x1=price[0];//固定点
		double y1=price[1];
		double x2=price[2+i*2];//随着i增涨的亮边
		double y2=price[3+i*2];
		double x3=price[4+i*2]; 
		double y3=price[5+i*2];
		//double temp=0.5*abs(x1*y2+x2*y3+x3*y1-x1*y3-x2*y1-x3*y2);
		temp=((x2-x1)*(y3-y1)-(x3-x1)*(y2-y1))/2;
		area+=temp;		
		x+=(x1+x2+x3)*temp/3.0;
		y+=(y1+y2+y3)*temp/3.0; 		 
	} 
	if(fabs(area-0)<0.0000001) cout<<"0.000 0.000"<<endl; 
	else cout<<setiosflags(ios::fixed)<<setprecision(3)<<fabs(area)
		 <<" "													
		 <<setiosflags(ios::fixed)<<setprecision(3)<<(x/area+y/area)												
		 <<endl;
}
int main(){
	cin>>n;//输入要运算的组数 
	while(n--){
		cin>>m;
		price=new double[m*2];
		for(int i=0;i<m*2;i++){
			cin>>price[i];//全部放入一个一维数组 
		}
		cal();
		delete []price;	
	}
	return 0;
}
代码二(引用于:点击打开链接
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
struct Point{
 double x,y;
};
int main()
{
    int n,t;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        Point p1,p2,p3;
        double gx,gy,sumarea;
        gx=gy=sumarea=0;
        scanf("%lf%lf%lf%lf",&p1.x,&p1.y,&p2.x,&p2.y);
        for(int i=2;i<n;i++){
            scanf("%lf%lf",&p3.x,&p3.y);
            double area=((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))/2;
            gx+=(p1.x+p2.x+p3.x)*area;
            gy+=(p1.y+p2.y+p3.y)*area;
            sumarea+=area;
            p2=p3;
        }
        gx=gx/sumarea/3;
        gy=gy/sumarea/3;
        if(fabs(sumarea - 0) < 0.0000001)puts("0.000 0.000");
        else printf("%.3lf %.3lf\n",fabs(sumarea),gy+gx);
    }
    return 0;
}
代码三(引用于:点击打开链接
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define INF 0.0000001
const int N = 10010;
struct point{
	double x, y;
	point():x(0),y(0){}
}p[N];
int main(){
	int ncase;
	scanf("%d", &ncase);
	while(ncase--){
		int n;
		double result = 0;
		point ans;
		scanf("%d", &n);
		for(int i = 0; i < n; ++i)
			scanf("%lf%lf", &p[i].x, &p[i].y);
		for(int i = 1; i <= n; ++i){
			double temp = (p[i % n].x * p[i -1].y - p[i % n].y * p[i -1].x) / 2.0;
			result += temp;
			ans.x += temp * (p[i % n].x + p[i - 1].x) / 3.0;
			ans.y += temp * (p[i % n].y + p[i - 1].y) / 3.0;
		}
		if(fabs(result - 0) < INF)
			puts("0.000 0.000");
		else
			printf("%.3lf %.3lf\n", fabs(result), (ans.x + ans.y) / result); //result取绝对值
	}
	return 0;
}
/*
1
7
2 3
4 5
3 4
7 8
4 78
34 56
8 100
*/

(全文完)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值