欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

1016 - 计算几何之直线与线段的交 - Segments(POJ 3304)

程序员文章站 2022-04-01 15:51:10
...

传送门

 

题意

虽然题目是给了什么投影啊,什么奇奇怪怪的东西

但实际上也就是给你 n 条线段,询问是否存在一条直线能经过所有的线段

数据范围:n<=100

 

分析

这个数据范围有点友好啊……

我们先来想一个问题

若存在一条直线使其能穿过所有的线段,那我们一定可以将这条线段进行一定角度的旋转,然后使其恰好被卡在某两条线段的端点之间

也就是说若我们能够找到被某两个线段端点卡住的直线,使其穿过所有的线段,则一定存在一组合法解

根据逆反定理,若我们找不到这样的直线,则原题一定不存在合法解

由于数据范围很友好,我们就直接暴力枚举(n^3)

 

代码

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define eps 1e-8
#define N 105
using namespace std;
int T,n;
struct Point{
	double x,y;
	Point(){}
	Point(double _x,double _y):x(_x),y(_y){}
	friend inline Point operator +(const Point &a,const Point &b){
		return Point(a.x+b.x,a.y+b.y);
	}
	friend inline Point operator -(const Point &a,const Point &b){
		return Point(a.x-b.x,a.y-b.y);
	}
	friend inline Point operator *(double k,const Point &a){
		return Point(k*a.x,k*a.y);
	}
	friend inline double dot(const Point &a,const Point &b){
		return (a.x*b.x+a.y*b.y);
	}
	friend inline double cross(const Point &a,const Point &b){
		return (a.x*b.y-b.x*a.y);
	}
	friend inline double len(const Point &a){
		return sqrt(dot(a,a));
	}
	friend inline double dis (const Point &a,const Point &b){
		return len(a-b);
	}//向量常见的运算 
};
struct Line{
	Point a,b;
}line[N];
bool check(Point x,Point y){
	if(dis(x,y)<eps) return false;//必须要要的
	for(int i=1;i<=n;++i){
		if(cross(x-line[i].a,y-line[i].a)*cross(x-line[i].b,y-line[i].b)>eps) return false; 
	}
	return true;
}
int main(){
	scanf("%d",&T);
	int i,j,k;
	while(T--){
		scanf("%d",&n);
		for(i=1;i<=n;++i)
			scanf("%lf%lf%lf%lf",&line[i].a.x,&line[i].a.y,&line[i].b.x,&line[i].b.y);
		if(n==1){ printf("Yes!\n");continue; } 
		int flag=0;
		for(i=1;i<n;++i)
		{
			for(j=i+1;j<=n;++j){
				if(check(line[i].a,line[j].a)||check(line[i].a,line[j].b)||check(line[i].b,line[j].a)||check(line[i].b,line[j].b)){
					flag=1;
					break;
				}
			}
			if(flag){
				printf("Yes!\n");
				break;
			} 
		}
		if(!flag) printf("No!\n");
	}
	return 0;
}

 

相关标签: 计算几何