三维线段距离,分数类(Ardenia王国,LA 4973)
来源:互联网 发布:大学生网络课程答案 编辑:程序博客网 时间:2024/05/07 02:01
关于WA:
大白上说不平行或重合就异面。。。都没考虑相交。。。
我是因为没讨论清楚+异面直线公式错了+分数类运算爆longlong。
关于没讨论清楚:平行,重合要特判。相交直接输出0。异面的话s和t要在[0,1],否则特判。
关于异面直线公式错了:我没用大白上的代码,看不懂,算出来答案也是错的,不知道为什么。。。自己的算法就是用二维的点到线段距离模板,错了,也不知道为什么。。。最好只好用两点间距离公式。。。就对了。。。也不知道为什么。。。。。。。。。。我觉得可能是因为分数类运算爆longlong导致的奇怪错误吧。。。
关于分数类运算爆longlong:这个得小心到极致,就不会错了。具体一点讲就是因为在分数四则运算时不可避免地要进行通分,也就是要相乘,这个过程搞不好就爆longlong了,哪怕你事后再来约分也晚了。所以要先求出个gcd,然后在进行乘法的时候能除就除,不给这个数特别大的机会,如果除晚了也得爆。
关于TLE:
原因是滥用分数类。
每对两个分数进行一次运算,那就要进行一次通分,通分是要求gcd的,gcd的时间复杂度为O(logn),n可是longlong级别的,而且本题有1e5个数据。
讲具体一点,那就是当且仅当在计算距离的时候才使用分数类即可。
因为一直在debug,所以对源代码不断地进行了删改。为了方便自己使用,所以直接复制了两套模板,一套是longlong的,一套是重载了分数类的。所以这份代码又乱又长,不好理解。。。
本题还是一道很能让人历练的题的。。。学到了很多,以后会做的更好。
代码
#include<bits/stdc++.h>using namespace std;typedef long long ll;ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;}ll ggcd(ll a,ll b){ if(a==0&&b==0) return 1; return gcd(abs(a),abs(b));}ll lcm(ll a,ll b){ return a/gcd(a,b)*b;}struct Fs{ ll fz,fm; Fs(ll a=0,ll b=1):fz(a),fm(b) { yuefen(); } void yuefen() { ll fh; if((fz<0&&fm>0)||(fz>0&&fm<0)) fh=-1; else fh=1; if(fz<0) fz=-fz; if(fm<0) fm=-fm; ll x=gcd(fz,fm); fz/=x; fm/=x; fz*=fh; } void scan() { scanf("%lld",&fz); fm=1; } void prll() { printf("%lld %lld\n",fz,fm); } Fs operator + (const Fs& rhs) const { Fs ret; ll x; x=ggcd(fm,rhs.fm); ret.fz=rhs.fm/x*fz+fm/x*rhs.fz; ret.fm=fm/x*rhs.fm; ret.yuefen(); return ret; } Fs operator - (const Fs& rhs) const { Fs ret; ll x; x=ggcd(fm,rhs.fm); ret.fz=rhs.fm/x*fz-fm/x*rhs.fz; ret.fm=fm/x*rhs.fm; ret.yuefen(); return ret; } Fs operator * (const Fs& rhs) const { Fs ret; ll x,y; x=ggcd(fz,rhs.fm); y=ggcd(fm,rhs.fz); ret.fz=fz/x*rhs.fz/y; ret.fm=fm/y*rhs.fm/x; ret.yuefen(); return ret; } Fs operator / (const Fs& rhs) const { Fs ret; ll x,y; x=ggcd(fz,rhs.fz); y=ggcd(fm,rhs.fm); ret.fz=fz/x*rhs.fm/y; ret.fm=fm/y*rhs.fz/x; ret.yuefen(); return ret; } bool operator == (const Fs& rhs) const { return fz==rhs.fz&&fm==rhs.fm; } bool operator < (const Fs& rhs) const { ll x,y; x=ggcd(fz,rhs.fz); y=ggcd(fm,rhs.fm); return fz/x*rhs.fm/y<rhs.fz/x*fm/y; } Fs abs(const Fs& rhs) const { Fs ret=rhs; if(ret.fz<0) ret.fz=-ret.fz; if(ret.fm<0) ret.fm=-ret.fm; return ret; }};struct Point3{ ll x,y,z; Point3(ll x=0,ll y=0,ll z=0):x(x),y(y),z(z){} void scan() { scanf("%lld %lld %lld",&x,&y,&z); }};typedef Point3 Vector3;Point3 operator + (Point3 A,Vector3 B){ return Point3(A.x+B.x,A.y+B.y,A.z+B.z);}Vector3 operator - (Point3 A,Point3 B){ return Vector3(A.x-B.x,A.y-B.y,A.z-B.z);}Vector3 operator * (Vector3 V,ll t){ return Vector3(V.x*t,V.y*t,V.z*t);}Vector3 operator / (Vector3 V,ll t){ return Vector3(V.x/t,V.y/t,V.z/t);}bool operator == (Point3 A,Point3 B){ return A.x==B.x&&A.y==B.y&&A.z==B.z;}ll Dot(Vector3 A,Vector3 B){ return A.x*B.x+A.y*B.y+A.z*B.z;}Vector3 Cross(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);}ll Len2(Vector3 V){ return Dot(V,V);}ll Dist2(Point3 A,Point3 B){ return Len2(B-A);}ll DTS(Point3 P,Point3 A,Point3 B){ if(A==B) return Dist2(P,A); Vector3 V1=B-A; Vector3 V2=P-A; Vector3 V3=P-B; if(Dot(V1,V2)<0) return Len2(V2); else if(0<Dot(V1,V3)) return Len2(V3); else { ll t=Dot(P-A,V1)/Dot(V1,V1); return Dist2(P,A+V1*t); }}bool SegSegllersection(Point3 A,Point3 B,Point3 C,Point3 D){ if(A==C||A==D||B==C||B==D) return true; Vector3 n=Cross(B-A,D-C); if(Dot(n,A-C)==0) return true; else return false;}bool SegSegNormalllersection(Point3 A,Point3 B,Point3 C,Point3 D){ Vector3 V1=C-A; Vector3 V2=D-A; Vector3 V3=A-C; Vector3 V4=B-C; Vector3 C1=Cross(B-A,V1); Vector3 C2=Cross(B-A,V2); Vector3 C3=Cross(D-C,V3); Vector3 C4=Cross(D-C,V4); return Dot(C1,C2)<0&&Len2(Cross(C1,C2))==0&&Dot(C3,C4)<0&&Len2(Cross(C3,C4))==0;}ll LD3D(Point3 p1,Vector3 u,Point3 p2,Vector3 v){ return (Dot(u,v)*Dot(v,p1-p2)-Dot(v,v)*Dot(u,p1-p2))/(Dot(u,u)*Dot(v,v)-Dot(u,v)*Dot(u,v));}struct Poll3{ Fs x,y,z; Poll3(Fs x=Fs(),Fs y=Fs(),Fs z=Fs()):x(x),y(y),z(z){} void scan() { x.scan(); y.scan(); z.scan(); }};typedef Poll3 Vecll3;Poll3 operator + (Poll3 A,Vecll3 B){ return Poll3(A.x+B.x,A.y+B.y,A.z+B.z);}Vecll3 operator - (Poll3 A,Poll3 B){ return Vecll3(A.x-B.x,A.y-B.y,A.z-B.z);}Vecll3 operator * (Vecll3 V,Fs t){ return Vecll3(V.x*t,V.y*t,V.z*t);}Vecll3 operator / (Vecll3 V,Fs t){ return Vecll3(V.x/t,V.y/t,V.z/t);}bool operator == (Poll3 A,Poll3 B){ return A.x==B.x&&A.y==B.y&&A.z==B.z;}Fs Dot(Vecll3 A,Vecll3 B){ return A.x*B.x+A.y*B.y+A.z*B.z;}Vecll3 Cross(Vecll3 A,Vecll3 B){ return Vecll3(A.y*B.z-A.z*B.y,A.z*B.x-A.x*B.z,A.x*B.y-A.y*B.x);}Fs Len2(Vecll3 V){ return Dot(V,V);}Fs Dist2(Poll3 A,Poll3 B){ return Len2(B-A);}Fs DTS(Poll3 P,Poll3 A,Poll3 B){ if(A==B) return Dist2(P,A); Vecll3 V1=B-A; Vecll3 V2=P-A; Vecll3 V3=P-B; if(Dot(V1,V2)<Fs(0,1)) return Len2(V2); else if(Fs(0,1)<Dot(V1,V3)) return Len2(V3); else { Fs t=Dot(P-A,V1)/Dot(V1,V1); return Dist2(P,A+V1*t); }}bool SegSegllersection(Poll3 A,Poll3 B,Poll3 C,Poll3 D){ if(A==C||A==D||B==C||B==D) return true; Vecll3 n=Cross(B-A,D-C); if(Dot(n,A-C)==Fs(0,1)) return true; else return false;}bool SegSegNormalllersection(Poll3 A,Poll3 B,Poll3 C,Poll3 D){ Vecll3 V1=C-A; Vecll3 V2=D-A; Vecll3 V3=A-C; Vecll3 V4=B-C; Vecll3 C1=Cross(B-A,V1); Vecll3 C2=Cross(B-A,V2); Vecll3 C3=Cross(D-C,V3); Vecll3 C4=Cross(D-C,V4); return Dot(C1,C2)<Fs(0,1)&&Len2(Cross(C1,C2))==Fs(0,1)&&Dot(C3,C4)<Fs(0,1)&&Len2(Cross(C3,C4))==Fs(0,1);}Poll3 sb(Point3 A){ return Poll3(Fs(A.x,1),Fs(A.y,1),Fs(A.z,1));}Fs SegSegDist(Point3 A,Point3 B,Point3 C,Point3 D){ Point3 P1=A; Point3 P2=C; Vector3 V1=B-A; Vector3 V2=D-C; ll a=Dot(P2-P1,V1); ll b=Dot(V2,V1); ll c=Dot(V1,V1); ll d=Dot(P2-P1,V2); ll e=Dot(V2,V2); ll f=Dot(V1,V2); ll FM=b*f-c*e; if(FM==0||SegSegllersection(A,B,C,D)) { if(SegSegNormalllersection(A,B,C,D)) return Fs(0,1); Fs ret=Fs(10000,1); Poll3 a=sb(A),b=sb(B),c=sb(C),d=sb(D); ret=min(ret,DTS(a,c,d)); ret=min(ret,DTS(b,c,d)); ret=min(ret,DTS(c,a,b)); ret=min(ret,DTS(d,a,b)); return ret; } ll FZ1=c*d-a*f; ll FZ2=b*d-a*e; Fs t=Fs(FZ1,FM); Fs s=Fs(FZ2,FM); if(Fs(0,1)<t&&t<Fs(1,1)&&Fs(0,1)<s&&s<Fs(1,1)) return DTS(sb(C)+sb(V2)*t,sb(A),sb(B)); else { Fs ret=Fs(10000,1); Poll3 a=sb(A),b=sb(B),c=sb(C),d=sb(D); ret=min(ret,DTS(a,c,d)); ret=min(ret,DTS(b,c,d)); ret=min(ret,DTS(c,a,b)); ret=min(ret,DTS(d,a,b)); return ret; }}int main(){ //freopen("data.txt","r",stdin); //freopen("wrong.txt","w",stdout); ll T; Point3 A,B,C,D; scanf("%lld",&T); while(T--) { A.scan(); B.scan(); C.scan(); D.scan(); SegSegDist(A,B,C,D).prll(); } return 0;}
0 0
- 三维线段距离,分数类(Ardenia王国,LA 4973)
- LA 4973 Ardenia 空间中线段的距离 要求用有理数输出
- uva 1469 - Ardenia(几何+分数)
- 移动微小的距离,线段相交,计算几何(怪物陷阱,LA 2797)
- 三维几何之求空间俩线段的公垂线,以及分数类
- lightoj 1240 计算机图论(计算三维点到线段的距离)
- 三维几何,四面体(压纸器,LA 4795)
- LA 4108 (线段树)
- uvalive 4730王国kingdom(并查集+线段树)
- LA 3938 线段树(区间合并)
- P1659 河蟹王国 线段树
- HDU6070(分数规划+线段树)
- LA 3938( 线段树)
- LA 2191 (线段树)
- HDU 1140 War on Weather (三维点之间距离)
- HDU 4617 Weapon(计算几何、三维直线距离)
- LA - 4329 - Ping pong(树状数组/线段树)
- LA 2191电位计(线段树模板题)
- MYSQL 优化常用方法
- 读书笔记 读书 <<要么健身要么读书,别再说无聊>>
- 设计模式六大原则(1):单一职责原则
- 在使用myeclipse SVN下载项目终止报错和提交代码时,不出现注释框的尝试解决办法
- 创建sftp用户 只允许访问指定目录 操作命令
- 三维线段距离,分数类(Ardenia王国,LA 4973)
- TPS和QPS
- 【Oracle数据库】限制数据和对数据排序
- tar命令的详细解释
- position absolute relative
- 打包命令行输出IPA文件
- python--继承
- 反射基础一
- MYSQL-基础—存储过程