SP35 【EQBOX - Equipment Box】
幾何題,手推公式。
兩個長方形。如圖(1):
把一個放到另一個裡面。注意不包含邊界。怎麼判斷?
為了方便計算我們首先排序,確保長是長,寬是寬;長在前,寬在後。
if(a<b)
swap(a,b);
if(x<y)
swap(x,y);
若 \(a>x\) 且 \(b>y\) ,則第二個長方形必定能夠放進第一個正方形(###);若 S(1) ≤ S(2) 或(1)的寬更小,則 (###) 必定不滿足。判定:
if(a>x&&b>y) return 1; if(a*b<=x*y||b<=y) return 0;
但是我們的想象力沒有這麼匱乏。我們還能斜著放。
機房某巨佬表示可以算出對角線(k)長度,若 k(1) > k(2) 則(###)成立。顯然是錯的。如圖(2):
抱歉,畫不出來。
但是我們已經領會到思想了:這道題定性分析是不夠的,需要開始定量分析了。
考慮最優情況:兩個矩形中心重合時能夠最好地滿足(###)。我們已經調換了長寬,於是先把它們這樣放在一起 圖(3):
然後轉。懶得畫圖了。
然後再轉。轉到不能再轉: F 點, H 點與 AB , CD 的距離趨近於0,但並沒有接觸。當然我們可以將其看作接觸了 圖(4):
現在的形式大概比較明朗了:若(2)的水平寬小於 a ,則(###)成立。當然如果 k(2)過短以至於無法接觸,那顯然可以直接判定(###)。如圖(5):
證明:無論如何旋轉,既然 k(2)<b,a>b,E,G兩點自然更無法和 AD , BC 接觸。因此直接(###)。一會的程式碼中這個務必要考慮進來。
if(b>sqrt(x*x+y*y))
return 1;
如果可以接觸,保持它們角度不變。
當 EK<AB 時(###)。不能等於!為什麼自己想。
題目轉化為:已知 \(AB=a,AD=b,EF=x,EH=y\) ,求 \(EK\) .可利用的函式:\(sin;cos;arcsin;arccos.\)
由勾股定理,\(EG=\sqrt{x^2+y^2};\)
\(EK=EG·cosGEK;\)
\(AEF=π/2-AFE=π/2-AFH+EFH;\)
\(cosGEK=cos(π/2-AEF-EFH)=cos(AFH-2·EFH);\)
\(AFH=arcsin(b/\sqrt{x^2+y^2}),EFH=arccos(x/\sqrt{x^2+y^2});\)
\(EK=\sqrt{x^2+y^2}·cos(arcsin(b/\sqrt{x^2+y^2})-2·arccos(x/\sqrt{x^2+y^2}))(ans)\)
這是公式。
當 ans<a 時,就可以輸出了。注意 \(b/\sqrt{x^2+y^2}\) 務必小於1。
時間複雜度為 O(T)。( T 組資料)
公式寫成 c++ :
sqrt(x*x+y*y)*cos(asin(b/sqrt(x*x+y*y))-2*acos(x/sqrt(x*x+y*y)))<a;
下面是程式碼。很短。
#include<bits/stdc++.h>
using namespace std;
bool judge(double a,double b,double x,double y)
{
if(a<b)
swap(a,b);
if(x<y)
swap(x,y);
if(a>x&&b>y||b>sqrt(x*x+y*y))
return 1;
if(a*b<=x*y||b<=y)
return 0;
if(sqrt(x*x+y*y)*cos(asin(b/sqrt(x*x+y*y))-2*acos(x/sqrt(x*x+y*y)))<a)
return 1;
else
return 0;
}
int main()
{
int t;
cin>>t;
while(t--)
{
double a,b,x,y;
cin>>a>>b>>x>>y;
if(judge(a,b,x,y))
cout<<"Escape is possible.\n";
else
cout<<"Box cannot be dropped.\n";
}
return 0;
}