2019牛客多校第五场 I three points 1

传送门: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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值