多边形面积的最长平分线的依托答辩记录

熬夜肝没了

多边形面积的最长平分线

描述

平分凸多边形面积的线段有无数条,求其中最长的线段长度。

输入

第一行是凸多边形的顶点数n (3<=n<=5000),接下来是n行顶点坐标,按逆时针顺次输入。

n

x1 y1

. . .

xn yn

输出

所有平分该多边形面积的线段中,最长的长度值。结果保留6位小数。

        把自己卡到的点:

  1. 点乘、叉乘    进一步理解判断点在直线的左右侧问题
  2. 平面多边形坐标计算公式   ->鞋带定理  (注意回龙关系 最后的n-1要和0进行关联)
  3. 逆时针的顺序进行组合三角形 防止重叠面积
  4. 向量λ比例切割求坐标 ->同高三角形的面积比为底边边   (AP=0P-OA,AP=λAB,OP=AP+0A)
  5. 平面直线计算公式
#include<iostream>
#include<cmath>
#include<iomanip>
using namespace std;
#define zero 1E-8
typedef struct{
	double x;
	double y;
}Point;
double S_new_calc(Point a,Point b,Point c){
 	double t1,t2,t3,t4,t5,t6,sum;
	t1=a.x*b.y;
	t2=a.y*b.x;
	t3=b.x*c.y;
	t4=b.y*c.x;
	t5=c.x*a.y;
	t6=c.y*a.x;
	sum=0.5*fabs(t1+t3+t5-t2-t4-t6);
	return sum;
}
double vec_calc(Point a,Point b,double k,Point base){
	double tx,ty;
	double vx,vy,dis;
	vx=b.x-a.x,vy=b.y-a.y;
	vx=k*vx,vy=k*vy;
	tx=vx+a.x,ty=vy+a.y;
	dis=sqrt( (base.x-tx)*(base.x-tx) + (base.y-ty)*(base.y-ty) );
	return dis;
}
int main(){
	Point* point;
	int i,n,index1,index2,*index;
	double S,S_new,S_test,k,max,dis;
	S=S_new=S_test=max=0;
	cin>>n;
	point = new Point[n+20];
	index = new int[n+20];
	for(i=0;i<n;i++) cin>>point[i].x>>point[i].y;	
	for(i=0;i<n-1;i++){ //多边形面积 
		S= S + (point[i].x*point[i+1].y - point[i].y*point[i+1].x);
	}
		S= S + (point[n-1].x*point[0].y - point[n-1].y*point[0].x);
		S=fabs(S)/2.0;
	for(i=0;i<n;i++){ //各点为首的分割体 
		S_new=S_test=0;
		index[0]=i;
		for(int j=1;j<n;j++) if(j+i<n) index[j]=j+i;else if(j+i>=n) index[j]=j+i-n;
//		for(int j=0;j<n;j++) cout<<index[j]<<" ";
//		cout<<endl;
		index1=1,index2=index1+1;
		while(true){
			S_test=S_test+S_new_calc(point[index[index1]],point[index[index2]],point[index[0]]);
			if(S_test-S/2>=zero) break;
			S_new=S_test;
			index1=index2++;
		}
//		cout<<setiosflags(ios::fixed)<<setprecision(6)<<"S:"<<S<<" S_test:"<<S_test<<endl;
		k=(S*0.5-S_new)/(S_test-S_new);	
		dis=vec_calc(point[index[index1]],point[index[index2]],k,point[index[0]]);
 		max=dis-max>zero?dis:max;
	}
	
	cout<<setiosflags(ios::fixed)<<setprecision(6)<<max;
	delete []point;
	delete []index;
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值