多边形重心问题
时间限制:
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
本题最难的地方在于多边形的面积如何求解还有重心怎样求,感觉被数学知识虐死了,努力挤出微笑。
首先了解一下叉积求三角形面积:叉积计算方法如果用坐标表示向量
将多边形分为多个三角形,三角形x坐标平均值为三角形重心x坐标,求每个三角形的x坐标平均值*三角形面积的累加和,然后除以多边形面积就是多边形的重心x坐标,同理可求出y坐标;(面积可看作质量)
我是看了这个才整明白的。
以上一段出自 http://blog.csdn.net/idealistic/article/details/78006690
如果还不好理解,那就再结合 S = ( (x2- x0) * (y1 - y0) - (x1- x0) * (y2- y0) ) / 2 ; 将其展开 S=(x1y0-y1x0)/2+(x2y1-y2x1)/2+(x0y2-y0x2)/2; 也就是程序第二十五行。
第十七行,本来是吧这几个变量的置零都放在定义的时候,后来发现,如果都放在定义的时候,那么对于面积,到最后的总和就不是一组数据的了,而是所有组数的面积之和,就错了,所以每组循环结束之后,都要将这三个数据重新置零。
后来程序编译没有错误之后,不管输入的数据是什么,输出结果都是0.000 0.000,原因是输入输出竟然用了%f,基本的各式都忘记了,这个需要深刻反思!!这个题既考验人的逻辑思维,又考验人的细心程度。
#include<stdio.h> #include<math.h> #define N 10001 typedef struct { double x; double y; }Node; int main() { Node m[N]; int n,t,i; double s,sum,a_x,a_y; scanf("%d",&n); while(n--) { sum=0.0;a_x=0.0;a_y=0.0;//如果不重复置零,会导致面积和累加 scanf("%d",&t); for(i=0;i<t;i++) { scanf("%lf%lf",&m[i].x,&m[i].y);//输入用lf } for(i=1;i<=t;i++) { s=(m[i%t].x*m[i-1].y-m[i%t].y*m[i-1].x)/2.0;//求单个三角形的面积 sum+=s;//面积之和 a_x+=s*(m[i%t].x+m[i-1].x)/3.0;//每个三角形重心横坐标 a_y+=s*(m[i%t].y+m[i-1].y)/3.0;//每个三角形重心纵坐标 } if(sum>-0.0001&&sum<0.0001) { printf("0.000 0.000\n"); continue; } else printf("%.3lf %.3lf\n",fabs(sum),(a_x+a_y)/sum); //输入用lf } return 0; }
-
第一行有一个整数0<n<11,表示有n组数据;