HDU2150 Pipe

来源:互联网 发布:网络主播唱歌是真的吗 编辑:程序博客网 时间:2024/06/04 07:24

题目:http://acm.hdu.edu.cn/showproblem.php?pid=2150

判断线段是否相交的经典题目

#include <stdio.h>#include <stdlib.h>#include <assert.h>#define _DEBUG 0#define MAXN 30#define MAXK 100#define MAX(X,Y) (X)>(Y)?(X):(Y)#define MIN(X,Y) (X)<(Y)?(X):(Y)typedef struct{long long x;long long y;}Point;Point pipes[MAXN][MAXK];long long crossMultiply(const Point &p1,const Point &p2,const Point p3){return (p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y);}bool inSegment(const Point &p1,const Point &p2,const Point p3){int minx=MIN(p1.x,p2.x);int maxx=MAX(p1.x,p2.x);int miny=MIN(p1.y,p2.y);int maxy=MAX(p1.y,p2.y);return (p3.x>=minx && p3.x<=maxx&& p3.y>=miny && p3.y<=maxy);}bool isIntersect(const Point &p1,const Point &p2,const Point p3,const Point p4){//p1--P2与p3--p4线段是否相交long long d1=crossMultiply(p1,p2,p3);long long d2=crossMultiply(p1,p2,p4);long long d3=crossMultiply(p3,p4,p1);long long d4=crossMultiply(p3,p4,p2);if((d1>0 && d2<0 || d1<0 && d2>0) && (d3>0 && d4<0 || d3<0 && d4>0)){return true;}if(d1==0 && inSegment(p1,p2,p3))return true;if(d2==0 && inSegment(p1,p2,p4))return true;if(d3==0 && inSegment(p3,p4,p1))return true;if(d4==0 && inSegment(p3,p4,p2))return true;return false;}bool check(int row,int col){assert(row>0 && col>0);int i,j;for(i=0;i<row;i++){for(j=1;;j++){if(pipes[i][j].x == 100000 && pipes[i][j].y == 100000)//到达边界break;if(isIntersect(pipes[i][j-1],pipes[i][j],pipes[row][col-1],pipes[row][col])){//有交叉return true;}}}return false;}int main(){#if _DEBUG == 1freopen("2150.in","r",stdin);#endifint n,k;int i,j;while(scanf("%d",&n)!=EOF){bool flag = false;//1表示有交叉点,0表示没有for(i=0;i<n;i++){scanf("%d",&k);for(j=0;j<k;j++){scanf("%lld %lld",&pipes[i][j].x,&pipes[i][j].y);if(flag)//已判定有交叉点continue;if(i>=1 && j>=1 && check(i,j)){//如果检查与之前的点有交叉点flag=true;}}//放置一不可能的点,作为边界pipes[i][k].x = 100000;pipes[i][k].y = 100000;}printf("%s\n",flag?"Yes":"No");}return 0;}


 

原创粉丝点击