POJ 2653 线段相交

本文讨论了一种在大量线段中快速找出顶线段的方法,通过限制相交线段的数量来避免全暴力算法的超时问题。详细介绍了如何使用模板代码进行线段相交判断,并提出了优化策略,使算法能在复杂情况下高效运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是一个计算几何的题目。题意是,按顺序给一系列的线段,问最终哪些线段处在顶端。
   只需要穷举判断,当前的线段会与哪些线段有交点即可。也就是暴力求解,但是线段数目N有10的5次方,平方算法是不能过的。这个题
能过的原因是题目描述里面说了,top的stick不会超过1000个。那么修改下暴力的方式题目就能过了。
   从小到大枚举每个棍子,判断它是否与后面的棍子相交,如果相交直接把当前棍子的top属性置为false,然后break内层循环。这样就不
会超时了,暴力也是需要技巧的,这句话说的很对啊。

   判断2条线段是否相交的算法直接按照黑书上的模板代码写了,那个模板代码还不错吧。。。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;

const int n_max=100005;
const int m_max=1005;
const double eps=1e-6;
bool is_p[n_max];
struct point
{
	double x,y;
	void init(double tx,double ty)
	{
		x=tx;
		y=ty;
	}
};
struct segment
{
	point begin,end;
	void init(double x1,double y1,double x2,double y2)
	{
		begin.init(x1,y1);
		end.init(x2,y2);
	}
	void pp()
	{
		printf("%.2lf %.2lf %.2lf %.2lf\n",begin.x,begin.y,end.x,end.y);
	}
}seg[n_max];



int dblcmp(double p)
{
	if(fabs(p)<eps)
	{
		return 0;
	}
	return p>0?1:-1;
}

double det(double x1,double y1,double x2,double y2)
{
	return x1*y2 - x2*y1;
}

double cross(point a,point b,point c)
{
	return det(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}

bool segcross(segment s1,segment s2)
{
	return (dblcmp(cross(s1.begin,s2.begin,s2.end)) ^ dblcmp(cross(s1.end,s2.begin,s2.end))) == -2 &&
			(dblcmp(cross(s2.begin,s1.begin,s1.end)) ^ dblcmp(cross(s2.end,s1.begin,s1.end))) == -2;
}

int main()
{
	int n;
	while(~scanf("%d",&n),n)
	{
		memset(is_p,0,sizeof(is_p));
		double x1,y1,x2,y2;
		int i,j;
		for(i=1;i<=n;i++)
		{
			scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
			seg[i].init(x1,y1,x2,y2);
		}
		queue<int> q;
		for(i=1;i<=n;i++)
		{
			bool b=true;
			for(j=i+1;j<=n;j++)
			{
				if(segcross(seg[i],seg[j]))
				{
					b=false;
					break;
				}
			}
			if(b)
			{
				q.push(i);
			}
		}
		printf("Top sticks: ");
		while(q.size()>1)
		{
			printf("%d, ",q.front());
			q.pop();
		}
		printf("%d.\n",q.front());
		q.pop();
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值