Poj2653

Poj2653

   不知道你有没有玩过挑棍子的游戏,这道题就是相当于从天上按顺序扔几个棍子下来,问最上层的棍子是哪几个(为了显得不那么Low,下面把棍子换成线段)

解:没错,它考得还是叉积,话说既然这玩意儿这么有用数学老师讲课的时候怎么从来没提过呢。(小月月:别逗了你们目测法看线段相交还用叉积?)

首先构造一个队列,其中放的是当前仍然在最上层的线段,然后用当前线段去与当前队列中的线段发生关系,一旦相交,取而代之。这里的队列用类似链表的实现会更为便捷,因为链表这种数据结构非常方便插入,并且比较省空间。但是说真的不要一提到链表就用指针,写起来真心无力,不如用数字代替内存地址,更清晰也更方便静态查错。(这不代表用指针写不好,只是复杂一些,网络流用指针写速度谁跑得过)

#include<iostream>
#include<cstdio>
#define MAXN 101000
#define eps 1e-10
using namespace std;
struct point{
	double x,y;
	point(){x=y=0;}
	point(double _x,double _y){x=_x; y=_y;}
};
struct list{
	bool is_top;
	point s,e;
	int prev,next;
	list(){
		is_top=0;
		prev=next=0;
	}
}T[MAXN];int head;
point V(point start,point end){return point(end.x-start.x,end.y-start.y);}
double Cross(point a,point b){return a.x*b.y-b.x*a.y;}
bool cover(list a,list b){
	return (Cross(V(a.s,a.e),V(a.s,b.s))*Cross(V(a.s,a.e),V(a.s,b.e))<-eps)
	&&(Cross(V(b.s,b.e),V(b.s,a.s))*Cross(V(b.s,b.e),V(b.s,a.e))<-eps);
}int n;
int main(){
//	freopen("poj.in","r",stdin);
	double a,b,c,d;
	while(scanf("%d",&n)&&n){
		head=0;
		for(int i=1;i<=n;i++){
			scanf("%lf%lf%lf%lf",&T[i].s.x,&T[i].s.y,&T[i].e.x,&T[i].e.y);
			T[i].is_top=1; T[i].next=0; T[i].prev=head; T[head].next=i;
			for(int j=head;j;j=T[j].prev)
			if(cover(T[j],T[i])){
				T[j].is_top=0;
				T[T[j].prev].next=T[j].next;
				T[T[j].next].prev=T[j].prev;
			}head=i;
		}
		printf("Top sticks:");
		for(int i=1;i<n;i++) if(T[i].is_top) printf(" %d,",i);
		printf(" %d.\n",n); 
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值