【线段相交】 POJ 2653 Pick-up sticks

线段相交水题,维护一个队列就行。。。

#include <iostream>
#include <queue> 
#include <stack> 
#include <map> 
#include <set> 
#include <bitset> 
#include <cstdio> 
#include <algorithm> 
#include <cstring> 
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 1000005
#define maxm 2000005
#define eps 1e-10
#define mod 1000000007
#define INF 1e9
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid 
#define rson o<<1 | 1, mid+1, R 
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;

int dcmp(double d)
{
	if(fabs(d) < eps) return 0;
	else return d > eps ? 1 : -1;
}
struct point
{
	double x, y;
	point(double x = 0, double y = 0) : x(x), y(y) {}
	bool operator < (const point& b) const {
		if(dcmp(x - b.x) == 0) return dcmp(y - b.y) < 0;
		else return x < b.x;
	}
	bool operator == (const point& b) const {
		return dcmp(x - b.x) == 0 && dcmp(y - b.y) == 0;
	}
	point operator + (const point& b) const {
		return point(x + b.x, y + b.y);
	}
	point operator - (const point& b) const {
		return point(x - b.x, y - b.y);
	}
	point operator * (double b) const {
		return point(x * b, y * b);
	}
	point operator / (double b) const {
		return point(x / b, y / b);
	}
	void out(void)
	{
		printf("x = %.3f y = %.3f\n", x, y);
	}
};
typedef point vec;

//点积
double dot(vec a, vec b)
{
	return a.x * b.x + a.y * b.y;
}
//向量的长度
double length(vec a)
{
	return sqrt(dot(a, a));
}
//两个向量的夹角
double angle(vec a, vec b)
{
	return acos(dot(a, b) / length(a) / length(b));
}
//向量叉积
double cross(vec a, vec b)
{
	return a.x * b.y - a.y * b.x;
}
//向量旋转,rad是弧度
vec rotate(vec a, double rad)
{
	return vec(a.x * cos(rad) - a.y * sin(rad), a.x * sin(rad) + a.y * cos(rad));
}
//求法向量,顺时针旋转90度
vec normal(vec a)
{
	double L = length(a);
	return vec(-a.y / L, a.x / L);
}
//求两条直线的交点,调用前要确保两条直线相交
point intersection(point a, vec v1, point b, vec v2)
{
	vec u = a - b;
	double t = cross(v2, u) / cross(v1, v2);
	return a + v1 * t;
}
//求点到直线的距离
double distoline(point p, point a, point b)
{
	vec v1 = b - a, v2 = p - a;
	return fabs(cross(v1, v2)) / length(v1);
	//如果不取绝对值得到的是有向距离
}
//求点到线段的距离
double distosegment(point p, point a, point b)
{
	if(a == b) return length(p - a);
	vec v1 = b - a, v2 = p - a, v3 = p - b;
	if(dcmp(dot(v1, v2)) < 0) return length(v2);
	else if(dcmp(dot(v1, v3)) > 0) return length(v3);
	else return fabs(cross(v1, v2)) / length(v1);
}
//点在线段上的投影
point projection(point p, point a, point b)
{
	vec v = b - a;
	return a + v * (dot(v, p - a) / dot(v, v));
}
//已经知道p在ab直线上,判断p和线段ab的关系
//p在不在线段上返回1,在线段端点返回0,在线段上返回-1
int onseg(point p, point a, point b)
{
	if(fabs(a.x - b.x) > fabs(a.y - b.y)) return dcmp(p.x - a.x) * dcmp(p.x - b.x);
	else return dcmp(p.y - a.y) * dcmp(p.y - b.y);
}
//线段相交,规范相交返回1,不规范相交返回2,不相交返回0
bool segtoseg(point a1, point b1, point a2, point b2)
{
	int d1 = dcmp(cross(b1 - a1, a2 - a1));
	int d2 = dcmp(cross(b1 - a1, b2 - a1));
	int d3 = dcmp(cross(b2 - a2, a1 - a2));
	int d4 = dcmp(cross(b2 - a2, b1 - a2));
	if(d1 * d2 < 0 && d3 * d4 < 0) return 1;
	if(d1 == 0 && onseg(a2, a1, b1) <= 0) return 2;
	if(d2 == 0 && onseg(b2, a1, b1) <= 0) return 2;
	if(d3 == 0 && onseg(a1, a2, b2) <= 0) return 2;
	if(d4 == 0 && onseg(b1, a2, b2) <= 0) return 2;
	return 0;
	
}

struct segment
{
	point a, b;
}s[maxn];
int q[2][1005];
int n;
void work(void)
{
	int now = 0, cnt = 0, next;
	for(int i = 1; i <= n; i++) {
		scanf("%lf%lf%lf%lf", &s[i].a.x, &s[i].a.y, &s[i].b.x, &s[i].b.y);
		next = now ^ 1;
		int t = 0;
		for(int j = 1; j <= cnt; j++)
			if(segtoseg(s[q[now][j]].a, s[q[now][j]].b, s[i].a, s[i].b) == 0)
				q[next][++t] = q[now][j];
		q[next][++t] = i;
		now = next, cnt = t;
	}
	printf("Top sticks: ");
	for(int i = 1; i <= cnt; i++) printf("%d%s", q[now][i], i != cnt ? ", " : ".\n");
}

int main(void)
{
	while(scanf("%d", &n), n != 0) work();
	return 0;
}


你可能感兴趣的:(poj)