HDU2150 Pipe

题目: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 == 1
	freopen("2150.in","r",stdin);
#endif
	int 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;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值