题目大意:
就
是
给
你
若
干
个
点
用
一
个
最
小
的
矩
形
把
这
些
点
覆
盖
掉
就是给你若干个点用一个最小的矩形把这些点覆盖掉
就是给你若干个点用一个最小的矩形把这些点覆盖掉
解题思路:
1.
首
先
很
明
显
我
们
可
以
对
这
些
点
求
一
个
凸
包
,
那
么
答
案
的
矩
形
的
一
定
是
卡
在
凸
包
外
面
的
1.首先很明显我们可以对这些点求一个凸包,那么答案的矩形的一定是卡在凸包外面的
1.首先很明显我们可以对这些点求一个凸包,那么答案的矩形的一定是卡在凸包外面的
2.
我
们
手
动
模
一
下
就
是
逐
渐
增
加
凸
包
上
面
的
点
数
,
去
看
一
下
最
小
的
矩
形
覆
盖
情
况
,
就
是
矩
形
的
一
条
边
有
两
个
点
在
上
面
就
是
和
凸
多
边
形
一
条
边
重
合
,
其
他
三
条
边
就
卡
在
其
他
三
个
点
上
面
。
2.我们手动模一下就是逐渐增加凸包上面的点数,去看一下最小的矩形覆盖情况,就是矩形的一条边有两个点在上面就是和凸多边形一条边重合,其他三条边就卡在其他三个点上面。
2.我们手动模一下就是逐渐增加凸包上面的点数,去看一下最小的矩形覆盖情况,就是矩形的一条边有两个点在上面就是和凸多边形一条边重合,其他三条边就卡在其他三个点上面。
3.
那
么
我
们
就
可
以
O
(
n
)
枚
举
一
下
矩
形
卡
着
哪
条
边
,
我
们
通
过
用
发
现
u
p
点
和
b
o
t
t
e
m
围
成
的
三
角
形
是
一
个
单
峰
函
数
。
l
e
f
t
和
r
i
g
h
t
点
的
在
b
o
t
t
o
m
处
的
投
影
也
是
一
个
凹
函
数
3.那么我们就可以O(n)枚举一下矩形卡着哪条边,我们通过用发现up点和bottem围成的三角形是一个单峰函数。left和right点的在bottom处的投影也是一个凹函数
3.那么我们就可以O(n)枚举一下矩形卡着哪条边,我们通过用发现up点和bottem围成的三角形是一个单峰函数。left和right点的在bottom处的投影也是一个凹函数
#include <iostream>
#include <cstdio>
#include <stack>
#include <sstream>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <iomanip>
#include <queue>
#include <algorithm>
#include <set>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define next Next
#define f first
#define s second
using namespace std;
const int maxn = 1e5 + 10;
const double eps = 1e-10;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
struct Point//点或向量
{
double x, y;
Point() {}
Point(double x, double y) :x(x), y(y) {}
};
typedef Point Vector;
double minsqr = 1e12;
int n;
Point ploy[maxn], sta[maxn], ans[10];
int dcmp(double x)//精度三态函数(>0,<0,=0)
{
if (fabs(x) < eps)return 0;
else if (x > 0)return 1;
return -1;
}
double Dot(Vector a, Vector b)//内积
{
return a.x*b.x + a.y*b.y;
}
Vector operator + (Vector a, Vector b)//向量加法
{
return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (Vector a, Vector 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);
}
double Distance(Point a, Point b)//两点间距离
{
return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(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;
}
bool operator<(Point a,Point b)
{
if(!dcmp(a.y-b.y)) return a.x<b.x;
return a.y<b.y;
}
double Cross(Vector a, Vector b)//外积
{
return a.x*b.y - a.y*b.x;
}
double DistanceToLine(Point A, Point M, Point N)//点A到直线MN的距离,Error:MN=0
{
return fabs(Cross(A - M, A - N) / Distance(M, N));
}
double relation(Point A, Point B, Point C)
{
return Dot(B - A, C - A) / Distance(A,B) / Distance(A,B);
}
//求C在AB所在直线的垂足P坐标
Point pedal(Point A, Point B, Point C)
{
double r = relation(A,B,C);
Point res;
res.x = A.x + r * (B.x - A.x);
res.y = A.y + r * (B.y - A.y);
return res;
}
bool cmp(Point a,Point b)
{
if(!dcmp(a.x-b.x)) return a.y<b.y;
return a.x<b.x;
}
int top = 0;
void Graham() {
sort(ploy,ploy+n,cmp);
for(int i = 0; i < n; ++ i) {
while(top >= 2 && dcmp(Cross(sta[top]-sta[top-1],ploy[i]-sta[top-1])) <= 0) top--;
sta[++top] = ploy[i];
}
int tmp = top;
for(int i = n - 2; i >= 0; -- i) {
while(top >= tmp + 1 && dcmp(Cross(sta[top]-sta[top-1],ploy[i]-sta[top-1])) <= 0) top--;
sta[++ top] = ploy[i];
}
top --;
}
void qiake() {
int left = 1, right = 1, up = 1;
for(int i = 1; i <= top; ++ i) {
while(dcmp(Cross(sta[i]-sta[up+1],sta[i+1]-sta[up+1]) - Cross(sta[i]-sta[up],sta[i+1]-sta[up])) >= 0) up = up % top + 1;
while(dcmp(Dot(sta[right+1] - sta[i],sta[i+1]-sta[i]) - Dot(sta[right]-sta[i],sta[i+1]-sta[i])) >= 0) right = right % top + 1;
if(i == 1) left = right;
while(dcmp(Dot(sta[i]-sta[i+1],sta[left+1]-sta[i+1]) - Dot(sta[i]-sta[i+1],sta[left]-sta[i+1])) >= 0) left = left % top + 1;
double L = DistanceToLine(sta[up],sta[i],sta[i+1]);
double Len = Distance(sta[i],sta[i+1]);//i 和 i + 1 点之间的长度
double botten = Dot(sta[right]-sta[i],sta[i+1]-sta[i]) / Len + Dot(sta[i]-sta[i+1],sta[left]-sta[i+1]) / Len - Len;
if(dcmp(minsqr - botten * L) > 0) {//逆时针存储矩形
minsqr = botten * L;
ans[0] = pedal(sta[i],sta[i+1],sta[right]);
ans[1] = pedal(ans[0],sta[right],sta[up]);
ans[2] = pedal(ans[1],sta[up],sta[left]);
ans[3] = pedal(sta[i],sta[i+1],sta[left]);
}
}
}
int main()
{
IOS;
cin >> n;
for(int i = 0; i < n; ++ i) {
double x, y;
cin >> x >> y;
ploy[i] = (Point){x,y};
}
Graham();
qiake();
cout << fixed << setprecision(5) << minsqr << endl;
int tmp = 0;
for(int i = 0; i <= 3; i ++)
if(ans[i]<ans[tmp]) tmp = i;
for(int i = 0; i < 4; ++ i)
cout << fixed << setprecision(5) << ans[(i + tmp) % 4].x + eps/*防止-0的出现*/ << " " << ans[(i + tmp) % 4].y + eps << endl;
}