HDU-2150 Pipe(math叉乘判断)

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">中文题,题意不用多少。</span>
这题也许两个线段当成直线算交点,然后判断交点横坐标在不在定义域内,感觉也可以,不过这种方法太低端,看了discuss里叉乘判断,于是我去学习了下线代里的向量积(ps.我是野生大一狗)。
百度题解都说这题是水题吧,我就给和我一样还没学过线代的孩子写下过程吧。(x是叉乘符号)
两个向量的向量积,是一个垂直于两个向量的向量,如果ABxAC,得到的结果是垂直于ABC这个平面的一个向量,这是用右手系判断的,如果是ABxAC,就是右手拇指朝上,手掌从AB边旋转小于180度的角度转到AC,这个结果就是拇指的方向。
如果AB和CD相交,可以画个图看看,ABxAC和ADxAB的拇指方向是相同的,ACxAD和BDxBC的拇指方向也是相同的。
ABxAC=(b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
(ABxAC)*(ADxAB)>=0,就是说明这两个向量积的方向相同,也就是姆指方向相同,也就是两个线段相交的判断条件。
其他的过程就是依次枚举。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define MAX 100+5
typedef long long LL;
const double pi=3.141592653589793;
const int INF=1e9;
const double inf=1e20;
const double eps=1e-6;
const int mod=1000000007;
struct point{
	int x,y;
}p[35][105];
double circulation(point a,point b,point c){
	return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
bool cross(point a,point b,point c,point d){
	if(max(a.x,b.x)>=min(c.x,d.x)&&
	   max(c.x,d.x)>=min(a.x,b.x)&&
	   max(a.y,b.y)>=min(c.y,d.y)&&
	   max(c.y,d.y)>=min(a.y,b.y)&&
	   circulation(a,b,c)*circulation(a,d,b)>=0&&
	   circulation(a,c,d)*circulation(b,d,c)>=0) return true;
	return false;
}
int main(){
	int n,k[35];
	while(cin>>n){
		memset(k,0,sizeof(k));
		memset(p,0,sizeof(p));
		for(int i=0;i<n;i++){
			cin>>k[i];
			for(int j=0;j<k[i];j++) scanf("%d%d",&p[i][j].x,&p[i][j].y);
		}
		if(n==1){
			printf("No\n");
			continue;
		}
		int flag=0;
		for(int i=0;i<n-1;i++){
			for(int j=1;j<k[i];j++){
				for(int t=i+1;t<n;t++){
					for(int h=1;h<k[t];h++){
						if(cross(p[i][j-1],p[i][j],p[t][h-1],p[t][h])){
							flag=1;
							break;
						}
					}
				}
			}
		}
		if(flag) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}


你可能感兴趣的:(Math,ACM)