NYOJ-3 多边形重心问题

题目描述:
在某个多边形上,取n个点,这n个点顺序给出,按照给出顺序将相邻的点用直线连接, (第一个和最后一个连接),所有线段不和其他线段相交,但是可以重合,可得到一个多边形或一条线段或一个多边形和一个线段的连接后的图形;
如果是一条线段,我们定义面积为0,重心坐标为(0,0).现在求给出的点集组成的图形的面积和重心横纵坐标的和;

输入,
第一行有一个整数0<n<11,表示有n组数据;
每组数据第一行有一个整数m<10000,表示有这个多边形有m个顶点;
输出,
输出每个多边形的面积、重心横纵坐标的和,小数点后保留三位;

代码:

#include<stdio.h>
#include<math.h>
const int N = 10005;
 
typedef struct 
{
	double x;
	double y;
}POINT;
 
POINT point[N];
 
inline double CrossProduct(int i)
{
	return point[i].x * point[i + 1].y - point[i + 1].x * point[i].y;
}
 
int main()
{
	int n,t;
	int i;
	double temp;
	double area,x,y;
	scanf("%d", &t);
	while(t--)
	{
		scanf("%d",&n);
		for(i = 0; i < n; ++i)
			scanf("%lf %lf",&point[i].x, &point[i].y);
 
		point[n].x = point[0].x;//记下第一个点,形成循环
		point[n].y = point[0].y;
 
		area = 0.0;
		x = 0.0;
		y = 0.0;
 
		for(i = 0; i < n; ++i)
		{
			temp = CrossProduct(i) / 2.0;//计算各个三角形的有向面积
			area += temp;
			x += temp * (point[i].x + point[i + 1].x) / 3.0;// 计算每个三角形的重心的横纵坐标并以该三角形的有向面积(与质量等价)作为权重
			y += temp * (point[i].y + point[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);
	}
}

思路:

求多边形面积:将n边形分割为n-2个三角形,分别求三角形面积,又因为已知顶点坐标,所以可以根据向量来求,原点到
某顶点的确定的向量就是这个顶点的坐标,设顶点为 p1, p2, …, pk, 则面积s

具体证明见链接:http://blog.csdn.net/hemmingway/article/details/7814494

对于重心, 设每个三角形面积为st, 对应向量为(x1, y1), (x2, y2), 那么x方向:(x1+x2)/3, y方向: (y1+y2)/3,假设总面积为s, 那么每个三角形权重为st/s, 那么

重心坐标为各个三角形重心乘以其面积求和后除以s,

具体证明见链接:http://blog.sina.com.cn/s/blog_6bc4930c01011xcd.html


叉乘/向量积:
向量的叉乘,即求同时垂直两个向量的向量,即c垂直于a,同时c垂直于b(a与c的夹角为90°,b与c的夹角为90°)
c = a×b = (a.yb.z-b.ya.z , b.xa.z-a.xb.z , a.xb.y-b.xa.y)
叉积的长度|a×b|可以解释成这两个叉乘向量a,b共起点时,所构成平行四边形的面积。

fabs函数:
用法:#include <math.h>
功能:求浮点数x的绝对值
说明:计算|x|, 当x不为负时返回 x,否则返回 -x

inline内联函数用法:
内联函数的基本思想在于将每个函数调用以它的代码体来替换,很可能会增加整个目标代码的体积过分地使用内联所产生的程序会因为有太大的体积而导致可用空间不够。即使可以使用虚拟内存,内联造成的代码膨胀也可能会导致不合理的页面调度行为(系统颠簸),这将使你的程序运行慢得象在爬,过多的内联还会降低指令高速缓存的命中率,从而使取指令的速度降低,因为从主存取指令当然比从缓存要慢。另一方面,如果内联函数体非常短,编译器为这个函数体生成的代码就会真的比为函数调用生成的代码要小许多。如果是这种情况,内联这个函数将会确实带来更小的目标代码和更高的缓存命中率!
在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来进行替换。由于在编译时将内联函数体中的代码替代到程序中,因此会增加目标程序代码量,进而增加空间开销,而在时间开销上不象函数调用时那么大,可见它是以目标代码的增加为代价来换取时间的节省。

◆总结:inline函数是提高运行时间效率,但却增加了空间开销。
即inline函数目的是:为了提高函数的执行效率(速度)。
非内联函数调用有栈内存创建和释放的开销
在C中可以用宏代码提高执行效率,宏代码不是函数但使用起来像函数,编译器用复制宏代码的方式取代函数调用,省去了参数压栈、生成汇编语言的CALL调用、返回参数、执行return等过程,从而提高速度。


const用法:
const修饰的数据类型是指常类型,常类型的变量或对象的值是不能被更新的。

typedef struct{int x;int y;}POINT;用法详解:

#include <stdio.h>
typedef struct
{
        int x;int y;
} POINT;
main()
{
      POINT a;
      a.x=10;
      a.y=22;
      printf("%d %d",a.x,a.y);
      getch();
}

typedef给一种数据类型一个别名,可以用别名来引用这种数据类型。

上述,定义了一个struct类型,他的别名是POINT。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值