1. 程式人生 > 其它 >SP35 【EQBOX - Equipment Box】

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;
}