LA 2797 平面区域dfs

题目大意:一个平面区域有n条线段,问能否从(0,0)处到达无穷远处(不穿过任何线段)

分析:若两条线段有一个端点重合,这种情况是不能从端点重合处穿过的 的。因此对每个端点延长一点,就可以避免这个问题。

n*2个端点加上起始点跟终点,两两之间不穿过任何线段的为可行路径建图。

最后以(0,0)开始dfs,看能否到达无穷远点。

 

#include<iostream>
#include<vector>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;

const double eps = 1e-12;
double dcmp(double x) 
{
	if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;
}

struct Point {
	double x, y;
	Point(double x=0, double y=0):x(x),y(y) { }
};

typedef Point Vector;

Vector operator + (const Point& A, const Point& B) {	return Vector(A.x+B.x, A.y+B.y);}
Vector operator - (const Point& A, const Point& B) {	return Vector(A.x-B.x, A.y-B.y);}
Vector operator * (const Point& A, double v) {	return Vector(A.x*v, A.y*v);}
Vector operator / (const Point& A, double v) {	return Vector(A.x/v, A.y/v);}
double Cross(const Vector& A, const Vector& B) { return A.x*B.y - A.y*B.x;}
double Dot(const Vector& A, const Vector& B) { return A.x*B.x + A.y*B.y;}
double Length(const Vector& A) { return sqrt(Dot(A,A));}
bool operator < (const Point& p1, const Point& p2) {
	return p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y);
}
bool operator == (const Point& p1, const Point& p2) {
	return p1.x == p2.x && p1.y == p2.y;
}

bool SegmentProperIntersection(const Point& a1, const Point& a2, const Point& b1, const Point& b2) {
	double c1 = Cross(a2-a1,b1-a1), c2 = Cross(a2-a1,b2-a1),
		c3 = Cross(b2-b1,a1-b1), c4=Cross(b2-b1,a2-b1);
	return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
}

bool OnSegment(const Point& p, const Point& a1, const Point& a2) {
	return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0;
}
const int maxn = 100 + 5;
int n,V;
const int maxv = 200 + 5;
int G[maxv][maxv], vis[maxv];
Point p1[maxn], p2[maxn];

// 在任何一条线段的中间(在端点不算)
bool OnAnySegment(Point p) {
	for(int i = 0; i < n; i++)
		if(OnSegment(p, p1[i], p2[i])) return true;
		return false;
}

// 与任何一条线段规范相交
bool IntersectWithAnySegment(Point a, Point b) {
	for(int i = 0; i < n; i++)
		if(SegmentProperIntersection(a, b, p1[i], p2[i])) return true;
		return false;
}

bool dfs(int u) 
{
	if(u == 1) return true; // 1是终点
	vis[u] = 1;
	for(int v = 0; v < V; v++)
		if(G[u][v] && !vis[v] && dfs(v)) return true;
		return false;
}

bool find_path() 
{
	// 构图
	int i,j;
	vector<Point> vertices;
	vertices.push_back(Point(0, 0)); // 起点
	vertices.push_back(Point(1e5, 1e5)); // 终点
	for(i = 0; i < n; i++) 
	{
		if(!OnAnySegment(p1[i])) vertices.push_back(p1[i]);
		if(!OnAnySegment(p2[i])) vertices.push_back(p2[i]);
	}
	V = vertices.size();
	memset(G, 0, sizeof(G));
	memset(vis, 0, sizeof(vis));
	for(i = 0; i < V; i++)
		for(j = i+1; j < V; j++)
			if(!IntersectWithAnySegment(vertices[i], vertices[j]))
				G[i][j] = G[j][i] = 1;
			return dfs(0);
}

int main()
{
	double x1, y1, x2, y2;
	int i;Vector v;
	while(scanf("%d",&n),n) 
	{
		for(i = 0; i < n; i++) 
		{
			scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
			Point a = Point(x1, y1);
			Point b = Point(x2, y2);
			v = b - a;
			v = v / Length(v);
			p1[i] = a - v * 1e-6;
			p2[i] = b + v * 1e-6;
		}
		if(find_path()) printf("no\n");
		else printf("yes\n");
	}
	return 0;
}

 

 

 

posted on 2013-11-19 20:00  雄..  阅读(209)  评论(0编辑  收藏  举报

导航