ICPC 2017 青岛 Spacecraft

题目地址:https://nanti.jisuanke.com/t/18518

 

人生第一篇博客。。。

 

用两个向量face和head模拟人的方位,向上或向下旋转ang角时,两个向量都旋转ang角,左右旋转时,face旋转ang角,head不变,自己感受一下就知道了。主要就是两个模板,三维空间中点到线段的距离以及向量的旋转。

 

 

#include<bits/stdc++.h>
#define eps 1e-10
#define pi acos(-1.0)
using namespace std;
int dcmp(double x){if (fabs(x)<eps)return 0;else return x<0?-1:1;}
struct Point3
{
    double x,y,z;
    Point3(double x=0,double y=0,double z=0):x(x),y(y),z(z){};
};
typedef Point3 Vector3;

Vector3 operator + (Vector3 a,Vector3 b){return Vector3(a.x+b.x,a.y+b.y,a.z+b.z);}
Vector3 operator - (Vector3 a,Vector3 b){return Vector3(a.x-b.x,a.y-b.y,a.z-b.z);}
Vector3 operator * (Vector3 a,double b){return Vector3(a.x*b,a.y*b,a.z*b);}
Vector3 operator / (Vector3 a,double b){return Vector3(a.x/b,a.y/b,a.z/b);}
bool operator == (Vector3 a,Vector3 b){return a.x==b.x && a.y==b.y && a.z==b.z;}
double Dot3(Vector3 a,Vector3 b){return a.x*b.x+a.y*b.y+a.z*b.z;}  //点积
double Length3(Vector3 a){return sqrt(Dot3(a,a));}
Vector3 Cross3(Vector3 a,Vector3 b) //叉积
{return Vector3(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);}
double Angle3(Vector3 a,Vector3 b){return acos(Dot3(a,b)/Length3(a)/Length3(b));}// 范围[0,180]

//点到线段的距离
double DistanceToSeg3(Point3 p,Point3 a,Point3 b)
{
    if(a==b) return Length3(p-a);
    Vector3 v1=b-a,v2=p-a,v3=p-b;
    if(dcmp(Dot3(v1,v2))<0) return Length3(v2);
    else if(dcmp(Dot3(v1,v3))>0) return Length3(v3);
    else return Length3(Cross3(v1,v2))/Length3(v1);
}

//点p绕向量ov旋转ang角度,旋转方向是向量ov叉乘向量op
Point3 rotate3(Point3 p,Vector3 v,double ang)
{
    double ret[3][3],a[3];
    v = v / Length3(v);
    ret[0][0] = (1.0 - cos(ang)) * v.x * v.x + cos(ang);
    ret[0][1] = (1.0 - cos(ang)) * v.x * v.y - sin(ang) * v.z;
    ret[0][2] = (1.0 - cos(ang)) * v.x * v.z + sin(ang) * v.y;
    ret[1][0] = (1.0 - cos(ang)) * v.y * v.x + sin(ang) * v.z;
    ret[1][1] = (1.0 - cos(ang)) * v.y * v.y + cos(ang);
    ret[1][2] = (1.0 - cos(ang)) * v.y * v.z - sin(ang) * v.x;
    ret[2][0] = (1.0 - cos(ang)) * v.z * v.x - sin(ang) * v.y;
    ret[2][1] = (1.0 - cos(ang)) * v.z * v.y + sin(ang) * v.x;
    ret[2][2] = (1.0 - cos(ang)) * v.z * v.z + cos(ang);
    for (int i=0;i<3;i++) a[i]=ret[i][0]*p.x+ret[i][1]*p.y+ret[i][2]*p.z;
    return Point3(a[0],a[1],a[2]);
}

Point3 face,head,st,en,a,vx=Point3(1,0,0),vy=Point3(0,1,0),vz=Point3(0,0,1);

int main()
{
    int T,n;
    scanf("%d",&T);
    while (T--)
    {
        double ans=1e8,ang,dx,dy,dz,d; char x[3];
        face=Point3(1,0,0); head=Point3(0,0,1);
        scanf("%lf%lf%lf",&st.x,&st.y,&st.z);
        scanf("%lf%lf%lf",&en.x,&en.y,&en.z);
        scanf("%d",&n);
        while (n--)
        {
            scanf("%lf %s %lf",&d,x,&ang);
            dx=d*cos(Angle3(vx,face));
            dy=d*cos(Angle3(vy,face));
            dz=d*cos(Angle3(vz,face));
            a=st+Point3(dx,dy,dz);
            ans=min(ans,DistanceToSeg3(en,st,a));
            st=a;
            if (x[0]=='U')
            {
                Vector3 v=Cross3(face,head);
                face=rotate3(face,v,ang);
                head=rotate3(head,v,ang);
            }else
            if (x[0]=='D')
            {
                Vector3 v=Cross3(head,face);
                face=rotate3(face,v,ang);
                head=rotate3(head,v,ang);
            }else
            if (x[0]=='L')
            {
                face=rotate3(face,head,ang);
            }else
            if (x[0]=='R')
            {
                Vector3 v=head*(-1);
                face=rotate3(face,v,ang);
            }
        }
        printf("%.2f\n",ans);
    }
    return 0;
}

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值