Description
Input
Output
Sample Input
5 1 1 4 2 2 3 3 1 1 -2.0 8 4 1 4 8 2 3 3 6 -2.0 3 0 0 1 1 1 0 2 1 2 0 3 1 0
Sample Output
Top sticks: 2, 4, 5. Top sticks: 1, 2, 3.
Hint
题目大意:按照一定的顺序扔小木棍,要找出最上层的木棍。
思路:我们可以从下向上找,如果一个线段的上面有与它交叉的线段,就说明这个木棍不合要求,上面一定有其他木棍.
那么问题关键就是线段交叉了。 都知道2个点在直线两边的条件是叉积的符号相反。
那么我们判断2次,即两个木棍的两个端点都在另一个木棍的两边,就说明线段交叉了。
#include <cstdlib>
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const double eps = 1E-8;
struct point
{
double x,y;
};
struct line
{
point a,b;
int c;
};
int sig(double d)
{
return (d>eps)-(d<-eps);
}
double cross(point &o,point &a,point &b)
{
return (a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);
}
line l[100003];
int main()
{
int i,j,n;
while(scanf("%d",&n),n)
{
for(i=1;i<=n;i++)
{
scanf("%lf %lf %lf %lf",&l[i].a.x,&l[i].a.y,&l[i].b.x,&l[i].b.y);
l[i].c=1;
}
for(i=1;i<n;i++)
{
for(j=i+1;j<=n;j++)
{
int d1,d2,d3,d4;
d1=sig(cross(l[i].a,l[j].a,l[j].b));
d2=sig(cross(l[i].b,l[j].a,l[j].b));
d3=sig(cross(l[j].a,l[i].a,l[i].b));
d4=sig(cross(l[j].b,l[i].a,l[i].b));
if((d1^d2)==-2&&(d3^d4)==-2)
{
// printf("[%d %d %d %d]\n",d1,d2,d3,d4);
l[i].c=0;
break;
}
}
}
printf("Top sticks: ");
for(i=1;i<n;i++)
if(l[i].c)
printf("%d, ",i);
printf("%d.\n",n);
}
system("PAUSE");
return EXIT_SUCCESS;
}