zoukankan      html  css  js  c++  java
  • 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
    ");
    		else printf("yes
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    移动端rem屏幕设置
    封装ajax库,post请求
    获取浏览器url参数
    身份证验证
    jq封装插件
    页面分享功能,分享好友、朋友圈判断,用share_type做标记 这里用的是jweixin-1.3.2.js
    @RequestParam和@RequestBody区别
    400报错
    IDEA中用Maven构建SSM项目环境入门
    Eclipse搭建Spring开发环境
  • 原文地址:https://www.cnblogs.com/xiong-/p/3432153.html
Copyright © 2011-2022 走看看