您的位置:首页 > 其它

1185: [HNOI2007]最小矩形覆盖

2016-12-29 21:18 337 查看

1185: [HNOI2007]最小矩形覆盖

Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge
Submit: 1392  Solved: 627

[Submit][Status][Discuss]

Description


 



Input

Output

Sample Input

Sample Output

HINT

Source

计算几何 vfleaking提供Spj

[Submit][Status][Discuss]


因为要矩形的面积最小,,所以肯定四条边上都要有一些点

这样的话这个矩形一定是在凸包上的,先求一下凸包,然后枚举每条边,就等于确定了一条边所在直线

对于一个矩形,确定了一条边上的直线,对边平行,另两条边垂直

这样的话旋转卡壳就可以卡出另外三条直线了。。。。。这样做O(nlogn)就行

不过有个点有出现重点,搞得凸包尴尬了。。先去重就没事了#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;

const int maxn = 5E4 + 50;
typedef double DB;
const DB eps = 1E-5;
bool fcmp(DB x,DB y) {return fabs(x - y) <= eps;}

struct Point{
DB x,y; Point(){}
Point(DB x,DB y): x(x),y(y){}
Point operator - (const Point &b) {return Point(x - b.x,y - b.y);}
Point operator + (const Point &b) {return Point(x + b.x,y + b.y);}
Point operator * (const DB &t) {return Point(x*t,y*t);}
Point operator / (const DB &t) {return Point(x/t,y/t);}
bool operator < (const Point &b) const
{
if (x < b.x) return 1;
if (x > b.x) return 0;
return y < b.y;
}
bool operator != (const Point &b) const
{
return !fcmp(x,b.x) || !fcmp(y,b.y);
}
}p[maxn],h[maxn*2],s[4];
typedef Point Vector;

struct Line{
Point P; Vector V; Line(){}
Line(Point P,Vector V): P(P),V(V){}
};

int n,tp,H,cur = 1;
DB Ans = 1E18;

int nex(int x) {return x < tp?x + 1:1;}
DB Dot(Vector v1,Vector v2) {return v1.x*v2.x + v1.y*v2.y;}
DB Cross(Vector v1,Vector v2) {return v1.x*v2.y - v2.x*v1.y;}
bool OnLeft(Line L1,Line L2)
{
DB ret = Cross(L2.V,L1.P - L2.P);
return ret > 0.0000;
}
DB Length(Vector v) {return sqrt(Dot(v,v));}

Point GetIntersection(Line L1,Line L2)
{
Vector u = L1.P - L2.P;
return L1.P + L1.V*Cross(L2.V,u)/Cross(L1.V,L2.V);
}

void Calc(Line A,Line B,Line C,Line D)
{
Point a = GetIntersection(D,A),b = GetIntersection(A,B);
Point c = GetIntersection(B,C),d = GetIntersection(C,D);
DB Now = Length(b - a)*Length(c - b);
if (Now >= Ans) return;
Ans = Now; s[0] = a; s[1] = b; s[2] = c; s[3] = d;
}

void Get_Hull()
{
for (int i = 1; i <= n; i++)
{
DB x,y; scanf("%lf%lf",&x,&y);
p[i] = Point(x,y);
}
sort(p + 1,p + n + 1);
for (int i = 2; i <= n; i++)
if (p[i] != p[i-1]) p[++cur] = p[i];
n = cur;
for (int i = 1; i <= n; i++)
{
while (tp > 1 && Cross(p[i] - h[tp-1],h[tp] - h[tp-1]) > 0.00)
--tp; h[++tp] = p[i];
}
H = tp;
for (int i = n - 1; i; i--)
{
while (tp > H && Cross(p[i] - h[tp-1],h[tp] - h[tp-1]) > 0.00)
--tp; h[++tp] = p[i];
}
}

void Print(DB x)
{
if (fcmp(x,0.00000)) printf("0.00000");
else printf("%.5f",x);
}

int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif

cin >> n; Get_Hull(); --tp;
int b = 2,c,d; c = d = H;
for (int a = 1; a <= tp; a++)
{
Vector A = h[nex(a)] - h[a],B = Point(-A.y,A.x);
Vector C = Point(-A.x,-A.y),D = Point(A.y,-A.x);
while (OnLeft(Line(h[b],B),Line(h[nex(b)],B))) b = nex(b);
while (OnLeft(Line(h[c],C),Line(h[nex(c)],C))) c = nex(c);
while (OnLeft(Line(h[d],D),Line(h[nex(d)],D))) d = nex(d);
Calc(Line(h[a],A),Line(h[b],B),Line(h[c],C),Line(h[d],D));
}
printf("%.5f\n",Ans); int pos = 0;
for (int i = 1; i < 4; i++)
if (s[i].y < s[pos].y) pos = i;
else if (fcmp(s[i].y,s[pos].y) && s[i].x < s[pos].x) pos = i;
for (int i = pos; ;)
{
Print(s[i].x); cout << ' ';
Print(s[i].y); cout << endl;
i = i == 3?0:i + 1; if (i == pos) break;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: