几何题,手推公式。
开始审题。
两个长方形。如图(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}))......!\)
这是公式。
当......!<a时,就可以骄傲地输出了。注意\(b/\sqrt{x^2+y^2}\)务必小于1。不然你会后悔的。尤其是DEV-c++,会很神奇的。
根据2001定律,时间复杂度为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;
}