应该算巨水了吧。。
不过写这道题是为了写点到线段的距离。
圆圆、矩矩不多说了,圆矩就看圆心到矩形四条边的距离是否不大于半径,某一不大于yes,都大于no。
思想如下,点与线段的位置关系分为3类:C1,C2,C3
图中AB为线段,C为点出现的情况。灰线代表过A、B与AB垂直的直线,黑线表示向量
从图中可以很容易看出来C2和C3算一种情况,在两条垂线的一侧。
注意C2,向量AC2,AB,可以看出向量夹角为钝角,同时向量BC2与向量BA夹角为锐角,
同理向量BC3,BA夹角为钝角,AC3,AB夹角为锐角。
那么什么公式可以表示向量夹角为钝角还是锐角呢?点积。
设t=向量AB,AC的点积*向量BA,BC的点积
若t<0则在两侧,点到线段AB的距离=min(|AC|,|BC|)
否则点到线段AB的距离=ABC的面积/|AB|
代码:
#include<stdio.h> #include<string.h> #include<math.h> #define eps 1e-8 struct point{ double x,y; }; struct tr{ point a,b,c,d; }u,v; struct circle{ point o; double r; }cu,cv; double chaji(point a,point b,point c){ return (c.x-a.x)*(b.y-a.y)-(c.y-a.y)*(b.x-a.x); } int dianji(point a,point b,point c){ double t; t=(c.x-a.x)*(b.x-a.x)+(c.y-a.y)*(b.y-a.y); if(t<-eps)return -1; if(t>eps)return 1; return 0; } double dis(point a,point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } double disl(point a,point b,point c){ if(dianji(b,c,a)*dianji(c,b,a)<0) return fmin(dis(a,b),dis(a,c)); else return fabs(chaji(a,b,c))/dis(b,c); } bool tin(tr u,point v){ if(v.x>u.a.x-eps&&v.x<u.c.x+eps&&v.y>u.c.y-eps&&v.y<u.a.y+eps) return 1; return 0; } void solve(circle u,tr v){ if(disl(u.o,v.a,v.b)<u.r+eps|| disl(u.o,v.b,v.c)<u.r+eps|| disl(u.o,v.c,v.d)<u.r+eps|| disl(u.o,v.d,v.a)<u.r+eps) puts("yes"); else puts("no"); } int main(){ char name1[50],name2[50]; int cs,f1,f2; double dr; scanf("%d",&cs); while(cs--){ scanf("%s",name1); if(!strcmp(name1,"circle")) scanf("%lf%lf%lf",&cu.r,&cu.o.x,&cu.o.y),f1=0; else{ scanf("%lf%lf%lf%lf",&u.a.x,&u.a.y,&u.c.x,&u.c.y); u.b.x=u.a.x;u.b.y=u.c.y; u.d.x=u.c.x;u.d.y=u.a.y; f1=1; } scanf("%s",name2); if(!strcmp(name2,"circle")) scanf("%lf%lf%lf",&cv.r,&cv.o.x,&cv.o.y),f2=0; else{ scanf("%lf%lf%lf%lf",&v.a.x,&v.a.y,&v.c.x,&v.c.y); v.b.x=v.a.x; v.b.y=v.c.y; v.d.x=v.c.x; v.d.y=v.a.y; f2=1; } if(!f1&&!f2){ dr=dis(cu.o,cv.o); if((dr-eps<cu.r+cv.r)&&(dr+eps>fabs(cu.r-cv.r))) puts("yes"); else puts("no"); } if(f1&&f2){ if(tin(u,v.a)||tin(u,v.b)||tin(u,v.c)||tin(u,v.d)|| tin(v,u.a)||tin(v,u.b)||tin(v,u.c)||tin(v,u.d)) puts("yes"); else puts("no"); } if(!f1&&f2)solve(cu,v); if(f1&&!f2)solve(cv,u); } return 0; }