http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=24011
给定n个点3~1e5,求出包含所有点的面积最小的矩形,周长最小矩形,输出最小面积和最小周长
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
#include <stack>
#include <set>
#include <algorithm>
using namespace std;
#define For(i,a,b) for(int (i)=(a);(i) < (b);(i)++)
#define rof(i,a,b) for(int (i)=(a);(i) > (b);(i)--)
#define IOS ios::sync_with_stdio(false)
#define lson l,m,rt <<1
#define rson m+1,r,rt<<1|1
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-11;
const double INF = 1e8;
const double PI = acos(-1.0);
const double TWO_PI = PI * 2;
template <class T> T sqr(T x) { return x * x;}
struct Point
{
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
};
typedef Point Vector;
//点-点=向量
Vector operator - (Point A, Point B) { return Vector(A.x-B.x,A.y-B.y);}
Vector operator *(Vector A, double p){return Vector(A.x*p,A.y*p); }
Vector operator /(Vector A, double p){return Vector(A.x/p,A.y/p); }
Vector operator +(Vector A, Vector B){ return Vector(A.x+B.x,A.y+B.y);}
//三态比较函数
int dcmp(double x){
if(fabs(x)<eps) return 0;
else return x<0?-1:1;
}
double Dot(Vector A, Vector B) { return A.x*B.x+A.y*B.y; }
double Cross (Vector A,Vector B){ return A.x*B.y-A.y*B.x; }
double Length(Vector A) {return sqrt(Dot(A,A)); }
double Dist(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
double Dist2(Point A, Point B){ return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y); }
double Angle(Vector A, Vector B){ return acos(Dot(A,B)/Length(A)/Length(B));}//返回A,B夹角[0,PI]
bool operator < (const Point &a,const Point &b) {return a.x<b.x||(a.x==b.x&&a.y<b.y); }
bool operator == (const Point &a,const Point &b){return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0; }
Vector Normal(const Vector& A) { double L = Length(A); return Vector(-A.y/L, A.x/L); }//左转90°
// 点集凸包
// 如果不希望在凸包的边上有输入点,把两个 <= 改成 <
// 如果不介意点集被修改,可以改成传递引用
vector<Point> ConvexHull(vector<Point> p)
{
sort(p.begin(), p.end());
p.erase(unique(p.begin(), p.end()), p.end());
int n=p.size();
int m=0;
vector<Point> ch(n+1);
for(int i=0;i<n;i++){
while(m>1&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
int k=m;
for(int i=n-2;i>=0;i--){
while(m>k&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;
ch[m++]=p[i];
}
if(n>1) m--;
ch.resize(m);
return ch;
}
//
void Qiake(vector<Point> & p,double & area,double & len){
vector<Point> ch=ConvexHull(p);
int n=ch.size();
ch.push_back(ch[0]);
int v=1,l=1,r=1;
area=1e15,len=1e15;
for(int u=0;u<n;u++){
while(Cross(ch[u+1]-ch[u],ch[v+1]-ch[v])>eps) v=(v+1)%n;
while(Dot(ch[u+1]-ch[u],ch[r+1]-ch[r])>eps) r=(r+1)%n;
if(u==0) l=(r+1)%n;
while(Dot(ch[u+1]-ch[u],ch[l+1]-ch[l])<-eps) l=(l+1)%n;
//u,v相对,l,r相对 u,r,v,l
double d=Dist(ch[u+1],ch[u]);
double h=Cross(ch[u+1]-ch[u],ch[v]-ch[u])/d;//u到当前边的距离
double w=(Dot(ch[r]-ch[u],ch[u+1]-ch[u])-Dot(ch[l]-ch[u],ch[u+1]-ch[u]))/d;
area=min(area,h*w);
len=min(len,2*(h+w));
}
}
int n;
vector<Point> p;
int main()
{
while(scanf("%d",&n)){
if(n==0) break;
p.clear();
for(int i=0;i<n;i++){
double x,y;
scanf("%lf%lf",&x,&y);
p.push_back(Point(x,y));
}
double ans1,ans2;
Qiake(p,ans1,ans2);
printf("%.2f %.2f\n",ans1,ans2 );
}
return 0;
}