传送门:https://ac.nowcoder.com/acm/contest/885/I
红太阳lts做这题做了5个小时没过。。。然后我觉得他的方法巨对我写了一发也通过0%.
学习了FDU老哥的代码,分了12种情况,终于过了。
根本思想是一个点固定在矩形的(0,0)的位置,然后旋转另外两条边,让一条边恰好搭在矩形的右边界上(不够长就在下边界上),然后看剩下的一条边的端点是否在矩形内,可以通过余弦定理求出角度然后求出端点坐标。
由于w,h的大小不知道,还有a,b,c任意排列的6种情况,所以枚举12种情况找一种合法的就行了,
#include<bits/stdc++.h>
using namespace std;
const double eps=9e-7;
double w,h;
double a[4];
double b[4];
bool flag;
struct node
{
double x,y;
node(double a=0,double b=0)
{
x=a;y=b;
}
void transxy(double sinb,double cosb)
{
double tx=x,ty=y;
x=tx*cosb-ty*sinb;
y=tx*sinb+ty*cosb;
}
}ans[4];
inline int sgn(double x)
{
if(x>-eps && x<eps) return 0;
if(x>0) return 1;
else return -1;
}
inline void prework()
{
scanf("%lf%lf",&w,&h);
for(int i=1;i<=3;i++)
scanf("%lf",&a[i]),b[i]=a[i];
}
inline bool jug(double w,double h,double a,double b,double c)
{
double sita1=acos((a*a+c*c-b*b)/(2*a*c));
double sita2=max(a>w?acos(w/a):0.0,c>w?acos(w/c)-sita1:0.0);
ans[1]=node{a*cos(sita2),a*sin(sita2)};
ans[2]=node{0.0,0.0};
ans[3]=node{c*cos(sita1+sita2),c*sin(sita1+sita2)};
for(int i=1;i<=3;i++)
if(ans[i].x<=-eps || ans[i].x>=w+eps || ans[i].y<-eps || ans[i].y>h+eps)
return false;
return true;
}
inline void mainwork()
{
int rev;
for(rev=0;rev<2;rev++)
{
if(jug(w,h,a[1],a[2],a[3]))
break;
if(jug(w,h,a[1],a[3],a[2]))
{
swap(ans[1],ans[2]);
break;
}
if(jug(w,h,a[2],a[1],a[3]))
{
swap(ans[2],ans[3]);
break;
}
if(jug(w,h,a[2],a[3],a[1]))
{
swap(ans[1],ans[2]);
swap(ans[2],ans[3]);
break;
}
if(jug(w,h,a[3],a[1],a[2]))
{
swap(ans[1],ans[3]);
swap(ans[2],ans[3]);
break;
}
if(jug(w,h,a[3],a[2],a[1]))
{
swap(ans[1],ans[3]);
break;
}
swap(w,h);
}
if(rev)
{
for(int i=1;i<=3;i++)
swap(ans[i].x,ans[i].y);
}
}
inline void print()
{
for(int i=1;i<=2;i++)
printf("%.9f %.9f ",ans[i].x,ans[i].y);
printf("%.9f %.9f\n",ans[3].x,ans[3].y);
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}