Pick-up Sticks
描述
Stan有n根棍子,他一次一根地将棍子随机地扔在地板上,然后,Stan试图找到在最上面的棍子,也就是没有其他的棍子压在这样的棍子上面,Stan已经注意到,最后扔出的棍子总在最上面,但他想知道所有在最上面的棍子。
输入
首先给出棍子总数n, 1<=n<=100000,接下来是n行,每行4个数,表示每根棍子左右端点的坐标,棍子列表的顺序是Stan扔棍子的顺序。n=0时表示结束。
输出
对每组测试用例,输出一行在最上面的棍子列表,列表顺序按扔棍子的顺序。
#include<iostream>
#define value 1e-8
#define LEFT -1
#define RIGHT 1
#define IN 0
#define N 100000
using namespace std;
typedef struct {
double x;
double y;
}point;
typedef struct {
point left;
point right;
}Stick;
int isDirection(Stick a,point b){
double sum;
sum=(a.right.y-a.left.y)*b.x+(a.left.x-a.right.x)*b.y+(a.right.x*a.left.y-a.left.x*a.right.y);
if(sum<-value) return LEFT;
else if(sum>value) return RIGHT;
else return IN;
}
int isCross(Stick a,Stick b){
int isValue1,isValue2;
isValue1=isDirection(a,b.left)*isDirection(a,b.right);
isValue2=isDirection(b,a.left)*isDirection(b,a.right);
if(isValue1*isValue2<0) return 0;
else if(isValue1*isValue2>0){
if(isValue1<0&&isValue2<0) return 1;
else return 0;
}
else if(isValue1*isValue2==0){
if(isValue1==0&&isValue2==0) return 1;
else return 0;
}
}
int main(){
int n,i,j,t,k,*top;
Stick *stick;
cin>>n;
while(n!=0){
stick = new Stick[n];
top = new int[n];
k=0;
for(i=0;i<n;i++){
cin>>stick[i].left.x>>stick[i].left.y>>stick[i].right.x>>stick[i].right.y;
}
for(i=0;i<n;i++){
t=0;
for(j=i+1;j<n;j++){
t=isCross(stick[i],stick[j]);
if(t) break;
}
if(t==0) top[k++]=i+1;
}
cout<<"Top sticks:";
for(i=0;i<k;i++){
cout<<" "<<top[i];
if(i+1<k) cout<<",";
}
cout<<"."<<endl;
delete []stick;
delete []top;
cin>>n;
}
return 0;
}
唯一觉得牛逼的地方是:isCross函数体
利用双重检索棍a和棍b的相交关系