(intermediate)2-SAT UVA 11930 Rectangles


  Rectangles 

Given a set of rectangles in the plane, determine if it is possible to choose one diagonal from each rectangle such that none of the selected diagonals intersect. Two diagonals intersect if they share at least one point. Note that the rectangles themselves are free to intersect.

\epsfbox{p11930.eps}

Input 

Input consists of several test cases. Each test case begins with an integer n ( 1$ \le$n$ \le$1000), representing the number of rectangles. This is followed by n lines each describing a rectangle using 8 integer numbers x1, y1, x2, y2, x3, y3, x4, y4, where each (xi, yi) is a vertex. All coordinate values are between -109 and 109. The input is terminated by a line containing `0' which should not be processed.

Output 

For each test case, output a line containing either `YES' if the selection is possible or `NO' if not.

Sample Input 

4
0    1    1    1    1    0    0    0
1    1    2    1    2    0    1    0
2    3    5    3    5    0    2    0
2    3    3    3    3    2    2    2
7
0    10    10    10    10    0    0    0
10   10    20    10    20    0    10   0
20   30    50    30    50    0    20   0
20   30    30    30    30    20   20   20
30   10    40    10    40    0    30   0 
5    0     30    0     30    -10  5    -10
0    0     5     0     5     -10  0    -10
0

Sample Output 

YES
NO





题意:给出很多的矩形,然后要你每个矩形都取一条对角线,问这些对角线有没有可能不想交(只要有一个公共点就算相交)


思路:我们对与每个矩形不是取这一条对角线就是取那条对角线,其实就是一个2-SAT问题,就是不是去这个就取那个,然后当我们取了某一条对角线的时候,就会有一些对角线跟这条边相交,那么这些矩形里面就只能取另一条对角线了,所以我们的见图办法就是(2*i+{0,1})作为点,表示取那一条对角线,如果取了对角线a会影响对角线b,那么我们就用一条有向边从a这个点指向b^1这个点,表示如果取了a就必须只能取b了,建好图后,我们用一用dfs就行了,在搜的过程中,假设自己搜到x这个点,如果x^1这个点也经过过的话,表示出现了矛盾,因为x,x^1只能取其中一个。那么在搜的时候如果发现dfs(x)返回false,那么我们就试一下dfs(x+1)行不行,(意思就是换一条边试试),如果还是不行,就表示不可能完成目标了。否则就继续换一条没搜过的边进行搜索就行了。

注意:题目给出的八个点不一定是按顺序的,自己判断一下那条线是对角线,如果两个向量叉乘不是0的话,表示两个向量相交,用这个判断就行了。


代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string.h>
#include<stack>
#include<cstring>
#include<vector>
using namespace std;
#define eps 1e-10
#define mp make_pair
const int maxn = 5000 + 5;
struct Point
{
	Point(const Point&p) { x = p.x, y = p.y; }
	Point(double xx = 0, double yy = 0) : x(xx), y(yy) { }
	double x;
	double y;
};

typedef Point Vector;

Vector operator+(Vector  v1, Vector  v2) { return Vector(v1.x + v2.x, v1.y + v2.y); }
Vector operator-(Vector  v1, Vector  v2) { return Vector(v1.x - v2.x, v1.y - v2.y); }
Vector operator*(Vector  v, double p) { return Vector(v.x*p, v.y*p); }
Vector operator/(Vector  v, double p) { return Vector(v.x / p, v.y / p); }

int dcmp(double x)
{
	if (fabs(x) < eps) return 0;
	return x < 0 ? -1 : 1;
}
bool operator < (Point  a, Point  b) { return dcmp(a.x - b.x)<0 || dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y)<0; }
bool operator==(const Point & a, const Point & b)
{
	return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
bool operator!=(const Point& a, const Point& b) { return !(a == b); }


double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }
double Dot(Vector  A, Vector  B) { return A.x*B.x + A.y*B.y; }


bool SegmentProperIntersection(Point a1, Point a2, Point b1, 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(Point p, Point a, Point b)
{
	return dcmp(Cross(a - p, b - p)) == 0 && dcmp(Dot(a - p, b - p)) < 0;
}

int n;

struct Segment
{
	Point a, b;
	Segment(Point a, Point b)  
	{
		this->a = a;
		this->b = b;
	}
};

vector<Segment> seg;
vector<int> G[maxn];
bool mark[maxn];
int S[maxn];
void add(int x, int y)
{
	G[x].push_back(y ^ 1);
	G[y].push_back(x ^ 1);
}


void input()
{
	seg.clear();
	for (int i = 0; i < maxn; ++i) G[i].clear();
	for (int i = 0; i < n; ++i)
	{
		int x1, y1, x2, y2, x3, y3, x4, y4;
		scanf("%d%d", &x1, &y1);
		scanf("%d%d", &x2, &y2);
		scanf("%d%d", &x3, &y3);
		scanf("%d%d", &x4, &y4);
		Point a(x1, y1), b(x2, y2), c(x3, y3), d(x4, y4);
		if (Cross(c - a, d - b) != 0)	{
			seg.push_back(Segment(a, c));
			seg.push_back(Segment(b, d));
		}
		else if (Cross(b - a, d - c) != 0) {
			seg.push_back(Segment(a, b));
			seg.push_back(Segment(c, d));
		}
		else if (Cross(d - a, b - c) != 0) {
			seg.push_back(Segment(a, d));
			seg.push_back(Segment(b, c));
		}
	}
	for (int i = 0; i < seg.size(); ++i)
	{
		Point a1 = seg[i].a, b1 = seg[i].b;
	//	printf("%.0lf %.0lf : %.0lf %.0lf\n", a1.x, a1.y, b1.x, b1.y);
		for (int j = i + 1; j < seg.size(); ++j)  
		{
			if (i == (j ^ 1)) continue;
			Point a2 = seg[j].a, b2 = seg[j].b;
//			printf("%.0lf %.0lf : %.0lf %.0lf\n", a2.x, a2.y, b2.x, b2.y);
//			printf("%d %d\n", i, j);
			if (SegmentProperIntersection(a1, b1, a2, b2))
				add(i, j);
			else if (OnSegment(a1, a2, b2)) 
				add(i, j);
			else if (OnSegment(b1, a2, b2))
				add(i, j);
			else if (OnSegment(a2, a1, b1))
				add(i, j);
			else if (OnSegment(b2, a1, b1)) 
				add(i, j);
			else if (a1 == a2 || a1 == b2) 
				add(i, j);
			else if (b1 == a2 || b1 == b2) 
				add(i, j);
		}
	}
}

int c;
bool dfs(int x)
{
	//printf("%d\n", x);
	if (mark[x ^ 1]) return false;
	if (mark[x]) return true;
	S[c++] = x;
	mark[x] = true;
	for (int i = 0; i < G[x].size(); ++i)
	if (!dfs(G[x][i])) return false;
	return true;
}

void outG()
{
	for (int i = 0; i < seg.size(); ++i)
	{
		printf("%d:", i);
		for (int j = 0; j < G[i].size(); ++j)
			printf(" %d", G[i][j]);
		cout << endl;
	}
}
bool solve()
{
	memset(mark, 0, sizeof(mark));
	//outG();
	for (int i = 0; i < seg.size(); i += 2) if (!mark[i] && !mark[i+1])
	{
		c = 0;
		if (!dfs(i)) {
			while (c>0) mark[S[--c]] = false;
			if (!dfs(i + 1)) return false;
		}
	}
	return true;
}


int main()
{
	while (scanf("%d", &n) && n)
	{
		input();
		if (solve()) printf("YES\n");
		else printf("NO\n");
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的影城管理系统,源码+数据库+论文答辩+毕业论文+视频演示 随着现在网络的快速发展,网上管理系统也逐渐快速发展起来,网上管理模式很快融入到了许多生活之中,随之就产生了“小徐影城管理系统”,这样就让小徐影城管理系统更加方便简单。 对于本小徐影城管理系统的设计来说,系统开发主要是采用java语言技术,在整个系统的设计中应用MySQL数据库来完成数据存储,具体根据小徐影城管理系统的现状来进行开发的,具体根据现实的需求来实现小徐影城管理系统网络化的管理,各类信息有序地进行存储,进入小徐影城管理系统页面之后,方可开始操作主控界面,主要功能包括管理员:首页、个人中心、用户管理、电影类型管理、放映厅管理、电影信息管理、购票统计管理、系统管理、订单管理,用户前台;首页、电影信息、电影资讯、个人中心、后台管理、在线客服等功能。 本论文主要讲述了小徐影城管理系统开发背景,该系统它主要是对需求分析和功能需求做了介绍,并且对系统做了详细的测试和总结。具体从业务流程、数据库设计和系统结构等多方面的问题。望能利用先进的计算机技术和网络技术来改变目前的小徐影城管理系统状况,提高管理效率。 关键词:小徐影城管理系统;Spring Boot框架,MySQL数据库
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值