HNOI2007 最小矩形覆蓋

2022-05-09 12:36:09 字數 2861 閱讀 4572

嘟嘟嘟

這道題我從昨天晚上5點做到今天下午3點半……差點就瘋了。

真是一道計算幾何好題呀!?

剛開始我以為矩形與座標軸平行,感覺省選題竟然這麼水。但是看完樣例後發現我錯了……

首先都知道要求凸包。寫**的時候一定要非常謹慎。對於重合或共線的點都要從棧中彈去,否則在後面的求矩形面積的時候會除以\(0\),然後就會想我一樣\(gg\)了快\(2\)個點。

然後,憑直覺能知道矩形的乙個邊一定和凸包的一條邊平行。那麼就能想到用旋轉卡殼維護矩形的另外三個最值點(不是頂點),即矩形最上點,最右點,最左點。

求最上點,和旋轉卡殼板子一樣,用叉積求面積就行了。

求最右點,用點積。對於當前直線\(ab\)和旋轉到的點\(ci\),如果\(\overrightarrow * \overrightarrow} > 0\),就接著往下旋轉。

求最左點,和最右點同理。只不過判斷條件是\(< 0\)。而且他的旋轉方向和上面相反,所以我又倒著跑了一遍旋轉卡殼。

接下來說怎麼求面積。

看這個圖就好了。

首先矩形的寬很好求,就是\(\delta abc\)以\(ab\)為底邊的高。用叉積求一遍面積然後除以底邊長完事。

然後求矩形的底邊長。我是把他分成了三部分:令\(a\)表示\(ab\)的長度,\(b\)表示\(\overrightarrow\)在\(\overrightarrow\)上的投影,\(c\)表示\(\overrightarrow\)在\(\overrightarrow\)上的投影,則底邊長\(l = |a| + |b| + |c|\)。

所以面積求完了啦!

最後是怎麼求矩形的四個頂點。

沿用上面的字母。

思路是從右下點\(g\)開始逆時針一次求。

\(g = b + \overrightarrow * \frac|}|}\)。

接下來求\(h\)。原來我是這麼求的:\(h = g + \overrightarrow * \frac|}|}\)。但是會有\(g, d\)重合的情況。所以就換了種求法,把\(\overrightarrow\)順時針旋轉\(90\)度得到\(\overrightarrow\),然後\(h = g + \overrightarrow * (- \frac|}|})\),其中\(|}\)就是矩形的高,上一問已經求過。

對於\(i, g\)同理,都是向量旋轉加伸長縮短,這裡就不講了。

好像就做完了……

感覺寫了一天的題也不怎麼難。還是自己菜啊……

需要注意的是這題卡精度,\(eps\)開到\(1e-10\)我才過。然後如果\(|a| < 1e-5\),直接輸出\(0.00000\),否則可能會輸出\(-0.00000\)……

#include#include#include#include#include#include#include#include#include#includeusing namespace std;

#define enter puts("")

#define space putchar(' ')

#define mem(a, x) memset(a, x, sizeof(a))

#define rg register

typedef long long ll;

typedef double db;

const int inf = 0x3f3f3f3f;

const db eps = 1e-10;

const int maxn = 5e4 + 5;

inline ll read()

inline void write(ll x)

int n;

struct point

; }

point operator + (const point& oth)const

; }

db operator * (const point& oth)const

db operator ^ (const point& oth)const //這是點積,不是位運算……

point operator * (db d)

; }

friend inline db dis(const point& a)

friend inline point rot(const point& a) //順時針旋轉90度

; }

}p[maxn], s;

bool cmp(point& a, point& b)

int st[maxn], top = 0;

void graham()

}struct rec

r[maxn];

db area(point a, point b, point c)

db pho(point a, point b, point c, point d)

inline int nxt(int x)

void rota1()

}inline int pre(int x)

void rota2() //單獨維護最左點

}point ans[5];

int main()

}printf("%.5lf\n", ans);

int id = 0;

for(int i = 1; i < 4; ++i)

if(ans[i].y < ans[id].y - eps || (fabs(ans[i].y - ans[id].y) < eps && ans[i].x < ans[id].x - eps)) id = i;

for(int i = 0; i < 4; ++i)

return 0;

}

HNOI2007 最小矩形覆蓋

給定一些點的座標,要求求能夠覆蓋所有點的最小面積的矩形,輸出所求矩形的面積和四個頂點座標 輸入格式 第一行為乙個整數n 3 n 50000 從第2至第n 1行每行有兩個浮點數,表示乙個頂點的x和y座標,不用科學計數法 輸出格式 第一行為乙個浮點數,表示所求矩形的面積 精確到小數點後5位 接下來4行每...

HNOI2007 最小矩形覆蓋

給定一些點的座標,要求求能夠覆蓋所有點的最小面積的矩形,輸出所求矩形的面積和四個頂點座標 第一行為乙個整數n 3 n 50000 從第2至第n 1行每行有兩個浮點數,表示乙個頂點的x和y座標,不用科學計數法 第一行為乙個浮點數,表示所求矩形的面積 精確到小數點後5位 接下來4行每行表示乙個頂點座標,...

HNOI2007 最小矩形覆蓋

給定一些點的座標,要求求能夠覆蓋所有點的最小面積的矩形,輸出所求矩形的面積和四個頂點座標 輸入格式 第一行為乙個整數n 3 n 50000 從第2至第n 1行每行有兩個浮點數,表示乙個頂點的x和y座標,不用科學計數法 輸出格式 第一行為乙個浮點數,表示所求矩形的面積 精確到小數點後5位 接下來4行每...