计算几何入门2--poj2653Pick-up sticks

来源:互联网 发布:d3.js 鼠标右键 编辑:程序博客网 时间:2024/06/15 02:02

给你一坨线段,问他们是否相交

不要被100000迷惑,暴力可过QAQ

先判断以两条线段为对角线的矩形是否相交,如相交则线段可能相交,上图是个例子:这里写图片描述
众所周知,连个线段如果相交,设a1b1与a2b2相交,那么向量b2a1、b2b1与向量a2b2的叉积的乘积为一个非正数,这就是跨立实验

为什么要先判断矩形相交呢?观察上图,这两条线段是可以通过跨立实验的这里写图片描述

代码

#include<map>#include<set>#include<cmath>#include<queue>#include<cstdio>#include<vector>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn=100000+10;int n,ans[maxn];bool flag[maxn];struct point{    double x,y;    point operator - (const point &a){        point t; t.x=x-a.x; t.y=y-a.y; return t;    } }pa[maxn],pb[maxn];double crossx(point a,point b){    return a.x*b.y-b.x*a.y;}bool check(int a,int b){    if (min(pa[a].x,pb[a].x)<=max(pa[b].x,pb[b].x))//先判矩形相交     if (min(pa[a].y,pb[a].y)<=max(pa[b].y,pb[b].y))    if (max(pa[a].x,pb[a].x)>=min(pa[b].x,pb[b].x))    if (max(pa[a].y,pb[a].y)>=min(pa[b].y,pb[b].y)){//跨立实验         point b2a1=pa[a]-pb[b]; point a1a2=pa[b]-pa[a];        point b2b1=pb[a]-pb[b]; point a1b2=pb[b]-pa[a];        point b2a2=pa[b]-pb[b]; point a1b1=pb[a]-pa[a];        if (crossx(b2a1,b2a2)*crossx(b2b1,b2a2)<=0)//两条线段各做一次             if (crossx(a1a2,a1b1)*crossx(a1b2,a1b1)<=0) return 1;    } return 0;}int main(){    while (~scanf("%d",&n)&&n){        if (!n) break;        for (int i=1;i<=n;++i){            flag[i]=1;            scanf("%lf%lf%lf%lf",&pa[i].x,&pa[i].y,&pb[i].x,&pb[i].y);        }        int Ans=0;        for (int i=1;i<=n;++i){            for (int j=i+1;j<=n;++j)                if (check(i,j)){                    flag[i]=0;break;                }            if (flag[i]) ans[++Ans]=i;        }         printf("Top sticks: ");        for (int i=1;i<Ans;++i) printf("%d, ",ans[i]);        if (Ans) printf("%d.\n",ans[Ans]);    }}
0 0