//其实不得不说这个问题的求解过程还挺麻烦的,我用的C++中简单的写法,没有调用复杂的函数;后边有最后的最优程序。
多边形重心问题
时间限制: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
公式S=(1/2)*(x1y2*1+x2y3*1+x3y1*1-x1y3*1-x2y1*1-x3y2*1)
我的程序:
#include <iostream>
#include <stdio.h>
#define M 10000
using namespace std;
int main()
{int n; int i,j; int m;
float a[11][M][2];
float x,y;
float s; float Sum;//面积
cin>>n;
//求面积和重心
for(i=1;i<=n;i++)
{s=0; Sum=0;x=0;y=0;
cin>>m;
for(j=1;j<=m;j++) //输入
cin>>a[i][j][0]>>a[i][j][1];
for(int p=3;p<=m;p++) {s=((a[i][p-1][0]-a[i][1][0])*(a[i][p][1]-a[i][1][1])-(a[i][p][0]-a[i][1][0])*(a[i][p-1][1]-a[i][1][1]))/2;
x+=(a[i][1][0]+a[i][p][0]+a[i][p-1][0])/3*s;
y+=(a[i][1][1]+a[i][p][1]+a[i][p-1][1])/3*s;
Sum+=s;
}
if(Sum==0) printf("0.000 0.000\n");
else printf("%0.3lf %0.3lf\n",-Sum,(x+y)/Sum);
}
return 0;
}
最优程序:
#include <stdio.h>
#include <math.h>
inline double g(double x1,double y1,double x2,double y2,double x3,double y3) { return (x1*y2+x2*y3+x3*y1-x1*y3-x2*y1-x3*y2)/2; } int main() { int n,m; scanf("%i",&n); while(n--){ scanf("%i",&m); m-=2; double x1,y1,x,y,xn,yn,gsx=0,gsy=0,s=0,cs=0; scanf("%lf%lf%lf%lf",&x1,&y1,&x,&y); while(m--) { scanf("%lf%lf",&xn,&yn); s+=(cs=g(x1,y1,x,y,xn,yn)); gsx+=(x1+x+xn)*cs/3; gsy+=(y1+y+yn)*cs/3; x=xn; y=yn; } printf("%.3f %.3f\n",fabsf(s),(s==0?0.0:fabsf((gsx+gsy)/s))); } }