题意:
给出一个多边形,顶点按照逆时针给出
让你选择两个点,使这两个点连线尽可能均分多边形面积
题解:
先求总面积,以及前缀面积和,然后运用尺取法
这里很好的运用了叉积的性质,因为叉积可以将不属于多边形的面积正负进行抵消
然后在运用尺取法的时候可以很容易求解顶点 i j 连线后其中一半的面积
这里注意尺取法的时候要处理超出面积一半的情况,因为超出面积一半的时候也可能是最小的面积差
最后的 j- - 一定不要忘记了
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define MAXN 200005
struct Point
{
double x,y;
Point(){}
Point(double _x,double _y){
x=_x,y=_y;
}
};
Point p[MAXN];
double num[MAXN];
double Cross(Point p1,Point p2,Point p3){
return (p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x);
}
double Dis(Point A, Point B){
return sqrt((A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y));
}
Point operator - (Point A,Point B){
return Point(A.x-B.x, A.y-B.y);
}
Point operator + (Point A, Point B){
return Point(A.x+B.x, A.y+B.y);
}
Point operator * (Point A, double p){
return Point(A.x*p, A.y*p);
}
bool operator == (Point A, Point B){
return (A.x-B.x) == 0 && (A.y-B.y) == 0;
}
Point t=Point(0,0);
double ConvexPolygonArea(int n)
{
num[0]=0;
for(int i=1;i<n;i++)
num[i]=num[i-1]+Cross(t,p[i-1],p[i])/2;
num[n]=num[n-1]+Cross(t,p[n-1],p[0])/2;
return num[n];
}
int main()
{
int n;
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
double area=ConvexPolygonArea(n);
double temp,sum=area/2,flag=area;
int i=0,j=1,left=0,right=1;
for(;i<n&&j<n;i++){
temp=fabs(num[j]-num[i]+Cross(t,p[j],p[i])/2);
while(j<n&&sum>=temp)
{
if(sum-temp<flag){
flag=sum-temp;
left=i,right=j;
}
j++;
temp=fabs(num[j]-num[i]+Cross(t,p[j],p[i])/2);
}
if(j<n&&(temp-sum<flag)){
flag=temp-sum;
left=i,right=j;
}
j--;
}
printf("%d %d\n",left+1,right+1);
}
return 0;
}