NYOJ 题目3多边形重心问题(数学几何)

95 篇文章 0 订阅
22 篇文章 0 订阅

多边形重心问题

时间限制: 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
上传者

iphxer

思路:http://blog.csdn.net/kay_zhyu/article/details/8805631

题目分析:好吧,这个题目基本上话了我一个小时去回顾以前学过的几何知识。下面我们来一点一点的分析。

1)重心就是重量的中心。其定义就是对整个图形分别从x方向和y方向进行密度积分,然后除以总面积,就得到了重心的x坐标和y坐标。这里由于图形每一点都是一样的,也就说说密度平均。好吧,说到积分,很多人就头疼了,好吧,我也烦这个。OK,换一个说法。多边形一定可以分成若干个不相交的三角形吧。其实通过重心和多边形的每一个点相连,就得到了我们要的三角形了。

2)把每一个三角形看成一个质心,那么我们刚刚所说的对密度进行积分其实分两个,x方向和y方向。那么x方向的积分就变成了对所有的三角形把  三角形的面积*该三角形重心的x坐标  的积加起来,同理y方向的积分就变成了对所有三角形把   三角形的面积*该三角形重心的y坐标  的积加起来。

3)每个三角形的面积怎么求?

其实在高中的时候我们就知道,已知三角形的两个边a,b。s=a*b*sin(ab所夹的角)。当然大学肯定学过叉乘。a×b=|a|*|b|*sin(ab所夹的角)。这里需要注意叉乘是有方向的,所以这个角必须是从a到b并且符合右手定律的那个角。

4)三角形的重心怎么求?

这个很简单啦!三个点的坐标的平均就可以了。公式不用我说了吧。

5)关键地方来了~

我开始说的把多边形分成若干个三角形的方法是让重心与每个点相连,但是这里重心是我们要求的东西,所以这样肯定不行。不过聪明的你肯定想到了以多边形的第一个点为准,然后分别与其它各点相连,然后形成的向量就是(point[0].x-point[i].x,point[0].y-point[i].y)和(point[0].x-point[i+1].x,point[0].y-point[i+1].y)。。或者说相邻的三个点就可以组成一个三角形则形成的向量就是(point[i].x-point[i-1].x, point[i].y-point[i-1].y)和(point[i].x-point[i+1].x, point[i].y-point[i+1].y)。OK,现在我告诉你,这两个方法都弱爆了。由于叉乘的特殊性质,前面我说的,它是有方向的,所以我们可以把这个相对的点移到任何一个角落。那么这个点既然是任意的,为什么不放在原点呢?你会奇怪为什么会这样。因为a×b=-b×a。so,你画画图试试~~~

OK~说了那么多累死我了,要还是不懂,对照着代码看吧~~


ac代码

#include<stdio.h>
#include<string.h>
#include<math.h>
struct s
{
	double x,y;
}p[10005];
double fun(int i)
{
	return p[i].x*p[i+1].y-p[i].y*p[i+1].x;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,i;
		double area,temp,x,y;
		scanf("%d",&n);
		for(i=0;i<n;i++)
			scanf("%lf%lf",&p[i].x,&p[i].y);
		p[n].x=p[0].x;
		p[n].y=p[0].y;
		area=0.0;
		x=0.0;
		y=0.0;
		for(i=0;i<n;i++)
		{
			temp=fun(i)/2.0;
			area+=temp;
			x+=temp*(p[i].x+p[i+1].x)/3.0;
			y+=temp*(p[i].y+p[i+1].y)/3.0;
		}
		area=fabs(area);
		if(area<0.0000001)
			printf("0.000 0.000\n");
		else
			printf("%.3lf %.3lf\n",area,fabs(x+y)/area);
	}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值