2013 多校第二场 hdu 4617 Weapon

hdu 4617

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4617

题目大意:给你n个无限长的圆柱,问你能否碰到,能的话,输出 “Lucky” ,不能的话,输出最小的距离。

思路:裸计算几何。比赛的时候叉积是记得,但是两直线的最短距离公式忘了,赛后百度了一下,就A掉了。。 这题应该很基础了吧,连我这种没学过计算几何的人都能很快A掉。。= = 

以前没怎么做过计算几何,木有什么模板,函数什么都是手写的。。

代码如下:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

struct Point
{
    double x,y,z;
    Point(){}
    Point(double a,double b,double c) : x (a),y(b),z(c){}
} cnt;

struct Ho
{
    Point cen,a,b;
    Point line;
    double r;
} ho[33];

Point cal_xl(Point a,Point b)
{
    cnt.x = a.x-b.x;
    cnt.y = a.y-b.y;
    cnt.z = a.z-b.z;
    return cnt;
}

Point cal_cj(Point a,Point b)
{
    return Point(a.y*b.z-b.y*a.z , b.x*a.z-a.x*b.z , a.x*b.y-b.x*a.y);
}

double cal_dis(Point a,Point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}

double mod(Point a)
{
    return sqrt(a.x*a.x+a.y*a.y+a.z*a.z);
}

double dc(Point a,Point b)
{
    return fabs(a.x*b.x+a.y*b.y+a.z*b.z);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        double a,b,c;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<3;j++)
            {
                scanf("%lf%lf%lf",&a,&b,&c);
                if(j==0) ho[i].cen = Point(a,b,c);
                else if(j==1) ho[i].a = Point(a,b,c);
                else ho[i].b = Point(a,b,c);
            }
        }
        for(int i = 0;i<n;i++)
        {
            ho[i].line = cal_cj(cal_xl(ho[i].cen,ho[i].a),cal_xl(ho[i].cen,ho[i].b));
            ho[i].r = cal_dis(ho[i].a,ho[i].cen);
        }
        int ok=0;
        double minn = 1e9;
        for(int i=0;i<n&&!ok;i++)
        {
            for(int j = i+1;j<n;j++)
            {
                Point n = cal_cj(ho[i].line,ho[j].line);
                double k = dc(n ,cal_xl(ho[i].cen,ho[j].cen))/mod(n);
                if(k<=ho[i].r+ho[j].r)
                {
                    ok=1;
                    break;
                }
                else
                {
                    minn = min(minn,k-ho[i].r-ho[j].r);
                }
            }
        }
        if(ok) puts("Lucky");
        else printf("%.2f\n",minn);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值