嘟嘟嘟
這道題我從昨天晚上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行每...