打算好好练练计算几何。
昨天经过反省决定戒掉一做题就看题解的恶习,结果今天做题就抓瞎了。。。
因为刚开始有很多公式方法不知道,所以完全自己做就毫无思路= =。还是忍住没看题解,打开了手边的CLRS,我本来以为这里面关于计算几何的篇幅很少,应该讲不了什么。
然后我发现我错了,经典就是经典。关于判断线段相交的方法,讲的非常清楚,每一步包括叉乘等细节都有很详细的讲解。
看完之后手动敲,1A,代码:
#include <stdio.h> #include <math.h> #include <algorithm> using namespace std; #define esp 1e-8 typedef struct Point { double x,y; }Point; struct Line { Point a,b; }l[110]; double direction(Point pi,Point pj,Point pk) //叉乘判断点pk在线段的哪一侧 { return (pk.x-pi.x)*(pj.y-pi.y)-(pj.x-pi.x)*(pk.y-pi.y); } bool on_segment(Point pi,Point pj,Point pk) //判断点pk是否在线段pi_pk上 { if(pk.x>=min(pi.x,pj.x)&&pk.x<=max(pi.x,pj.x)&&pk.y>=min(pi.y,pj.y)&&pk.y<=max(pi.y,pj.y)) return true; else return false; } bool judge(Point p1,Point p2,Point p3,Point p4) { int d1=direction(p3,p4,p1); int d2=direction(p3,p4,p2); int d3=direction(p1,p2,p3); int d4=direction(p1,p2,p4); if(((d1>0&&d2<0)||(d1<0&&d2>0))&&((d3>0&&d4<0)||(d3<0&&d4>0))) //分别判断两组点,满足每一组的两个点都不在同一侧即可确定相交 return true; else if(d1==0&&on_segment(p3,p4,p1)) //端点在线段上也算相交,下同 return true; else if(d2==0&&on_segment(p3,p4,p2)) return true; else if(d3==0&&on_segment(p1,p2,p3)) return true; else if(d4==0&&on_segment(p1,p2,p4)) return true; else return false; } int main(int argc, char const *argv[]) { //freopen("H:\\in.txt","r",stdin); int n; while(scanf("%d",&n),n) { int cnt=0; for(int i=0;i<n;i++) scanf("%lf%lf%lf%lf",&l[i].a.x,&l[i].a.y,&l[i].b.x,&l[i].b.y); for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) if(judge(l[i].a,l[i].b,l[j].a,l[j].b)) cnt++; printf("%d\n",cnt); } return 0; }
时间: 2024-10-13 15:25:18