給定一些點的座標,要求求能夠覆蓋所有點的最小面積的矩形,輸出所求矩形的面積和四個頂點座標
輸入格式:
第一行為乙個整數n(3<=n<=50000),從第2至第n+1行每行有兩個浮點數,表示乙個頂點的x和y座標,不用科學計數法
輸出格式:
第一行為乙個浮點數,表示所求矩形的面積(精確到小數點後5位),接下來4行每行表示乙個頂點座標,要求第一行為y座標最小的頂點,其後按逆時針輸出頂點座標.如果用相同y座標,先輸出最小x座標的頂點
題目簡單易懂。做法撲朔迷離。
首先,矩形的乙個邊一定和凸包的一條邊重合(???貌似無人會證???dalao說顯然,juruo說是結論??)。
然後可以旋轉卡殼
我們需要固定這樣幾個點:a/b/c/d/e
d是最高點,a,b是列舉的邊,c、e是左右最遠點。
d直接旋轉卡殼可以找到。
c,e滿足位置轉動單調性。
對於c,只要判斷,ba向量和ac向量夾角是銳角,
對於e,只要判斷,ba向量和be向量夾角是鈍角。
在此基礎上,c,e不斷移動到不行為止。
銳角鈍角可以用點積正負判斷。
算面積的話,高好說,就是d到ab的距離。
寬的話,是ab+(c在ab上的投影長度)+(e在ab上的投影長度)
投影長度可以用點積計算。
然後,矩形四個點怎麼算??
a就是投影。叉積計算即可。
其他三個點同理。
完畢。(ps:這個題貌似就只有乙個矩形滿足面積最小,,,,我也不知道為什麼。。。)
(但是我還是對每個矩形都求了一下四個點,然後判斷的)
#include#define reg register int#define il inline
#define numb (ch^'0')
using
namespace
std;
typedef
long
long
ll;il
void rd(int &x)
namespace
miracle
po(double xx,double
yy) po friend
operator +(po a,po b)
po friend
operator -(po a,po b)
bool friend operator
}a[n];
sets;
struct
vec vec(po a)
double
len()
};double
dis(po a,po b)
double
cross(vec a,vec b)
double
dot(vec a,vec b)
int fabs(double
t)double
hei(po p,po a,po b)
bool
cmp(po x,po y)
po sta[n];
inttop;
double
ans;
int mem[10
];po op[
10];
po tmp[
10];
intm;
intmain()
}int id=1
;
for(reg i=2;i<=n;++i)
if(id!=1) swap(a[1
],a[id]);
sort(a+2,a+n+1
,cmp);
sta[++top]=a[1
];
for(reg i=2;i<=n;++i)
//cout<
for(reg i=1;i<=top;++i)
inta,b,c,d,e;
a=1,c=1,b=top,e=top;d=1
;
while(fabs(dot(vec(sta[e-1]-sta[e]),vec(sta[a]-sta[b])))<=0) --e;
//n=233333;
for(reg a=1;a<=top;++a)
while(fabs(dot(vec(sta[e]-sta[e%top+1]),vec(sta[a]-sta[b])))>0) e=e%top+1
;
while(fabs(fabs(cross(vec(sta[d%top+1]-sta[b]),vec(sta[a]-sta[b])))>fabs(cross(vec(sta[d]-sta[b]),vec(sta[a]-sta[b]))))) d=d%top+1
;
double h=hei(sta[d],sta[a],sta[b]);
double d=dis(sta[a],sta[b]);
double l=d+fabs(dot(vec(sta[e]-sta[b]),vec(sta[a]-sta[b]))/d)+fabs(dot(vec(sta[c]-sta[a]),vec(sta[a]-sta[b]))/d);
//cout<
double aa=fabs(dot(vec(sta[e]-sta[b]),vec(sta[b]-sta[a]))/bb);
op[1]=po(sta[b].x-aa*(sta[a].x-sta[b].x)/bb,sta[b].y+aa*(sta[b].y-sta[a].y)/bb);
double cc=fabs(dot(vec(sta[c]-sta[a]),vec(sta[a]-sta[b]))/bb);
op[2]=po(sta[a].x+cc*(sta[a].x-sta[b].x)/bb,sta[a].y-cc*(sta[b].y-sta[a].y)/bb);
h=hei(sta[d],sta[a],sta[b]);
double tt=dis(op[2
],sta[c]);
op[3]=po(op[2].x+h*(sta[c].x-op[2].x)/tt,op[2].y+h*(sta[c].y-op[2].y)/tt);
double ee=dis(op[1
],sta[e]);
op[4]=po(op[1].x+h*(sta[e].x-op[1].x)/ee,op[1].y+h*(sta[e].y-op[1].y)/ee);
id=1
;
for(reg i=2;i<=4;++i)
if(fabs(ans-h*l)>0||(fabs(ans-h*l)==0&&op[id]1
])) }
}printf(
"%.5lf\n
",ans);
for(reg i=1;i<=4;++i)
return0;
}}intmain()
/*author: *miracle*
date: 2018/11/24 18:49:07
*/
HNOI2007 最小矩形覆蓋
給定一些點的座標,要求求能夠覆蓋所有點的最小面積的矩形,輸出所求矩形的面積和四個頂點座標 第一行為乙個整數n 3 n 50000 從第2至第n 1行每行有兩個浮點數,表示乙個頂點的x和y座標,不用科學計數法 第一行為乙個浮點數,表示所求矩形的面積 精確到小數點後5位 接下來4行每行表示乙個頂點座標,...
HNOI2007 最小矩形覆蓋
嘟嘟嘟 這道題我從昨天晚上5點做到今天下午3點半 差點就瘋了。真是一道計算幾何好題呀!剛開始我以為矩形與座標軸平行,感覺省選題竟然這麼水。但是看完樣例後發現我錯了 首先都知道要求凸包。寫 的時候一定要非常謹慎。對於重合或共線的點都要從棧中彈去,否則在後面的求矩形面積的時候會除以 0 然後就會想我一樣...
HNOI2007 最小矩形覆蓋
給定一些點的座標,要求求能夠覆蓋所有點的最小面積的矩形,輸出所求矩形的面積和四個頂點座標 輸入格式 第一行為乙個整數n 3 n 50000 從第2至第n 1行每行有兩個浮點數,表示乙個頂點的x和y座標,不用科學計數法 輸出格式 第一行為乙個浮點數,表示所求矩形的面積 精確到小數點後5位 接下來4行每...