链接:
#include <stdio.h>
int main()
{
puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢");
puts("网址:blog.csdn.net/vmurder/article/details/46608743");
}
题解:
对于一个点对,如果它的连线的方程的 x 为定值 ,即为一条竖线,那么我可以把所有点以 x 为第一键值, y 为第二键值排序,然后这条线两端的第一个点与这条线段做个三角形,其面积都可能更新答案。。
然后我们可以先把所有线按照斜率排个序,然后发现每次按序修改y轴,可以 O(1) 得到旋转坐标系后的点的序列。
可以观察此图(这是个小特例福利哦):
呃。就是每次旋转到一条斜率时,旋转前是是斜的 (A?>B),旋转完就变成了竖着的 (B?>A) ,此时只要简单交换一下 A、B 在序列中位置就好了~如下图:
代码:
(我才不会告诉你们虽然AC,但是实测时感觉貌似哪里挂了呢QwQ)
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1010
#define INF 1e60
#define Area(A,B,C) abs(xmul(A,B)+xmul(B,C)+xmul(C,A))
using namespace std;
struct Point
{
double x,y;
void read(){scanf("%lf%lf",&x,&y);}
bool operator < (const Point &A)const{return x<A.x;}
}p[N],Zero;
int id[N],cr[N];
struct Line
{
int u,v; // 点标号……
double k;
void keep(int _u,int _v)
{u=_u,v=_v,k=(p[u].y-p[v].y)/(p[u].x-p[v].x);}
bool operator < (const Line &A)const{return k<A.k;}
}l[N*N];
inline double xmul(Point B,Point C,Point A=Zero)
{return (C.y-A.y)*(B.x-A.x)-(B.y-A.y)*(C.x-A.x);}
int n,m;
double ans=INF;
void work(int u,int v)
{
if(id[u]>id[v])swap(u,v);
if(id[u]>1)ans=min(ans,Area(p[u],p[v],p[cr[id[u]-1]]));
if(id[v]<n)ans=min(ans,Area(p[u],p[v],p[cr[id[v]+1]]));
swap(id[u],id[v]),cr[id[u]]=u,cr[id[v]]=v;
}
int main()
{
// freopen("test.in","r",stdin);
int i,j;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
p[i].read();
id[i]=cr[i]=i;
}
sort(p+1,p+n+1);
for(i=1;i<=n;i++)for(j=i+1;j<=n;j++)
l[++m].keep(i,j);
sort(l+1,l+m+1);
for(i=1;i<=m;i++)work(l[i].u,l[i].v);
printf("%.2lf\n",ans/2.0);
return 0;
}
时间: 2024-10-08 13:42:54