HNOI2007 最小矩形覆蓋

2022-02-05 17:03:43 字數 3678 閱讀 8673

給定一些點的座標,要求求能夠覆蓋所有點的最小面積的矩形,輸出所求矩形的面積和四個頂點座標

輸入格式:

第一行為乙個整數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行每...