题目链接:poj2653
大意:有很多根木棍,如果后面的木根和前面的木棍有交叉的话,后面的木棍就会覆盖掉前面的木棍,问最后没有被覆盖的木棍数
思路:运用队列模拟,如果当前输入的木棍和前面的木棍交叉,那么将前面的那个木棍取出队列,否则的话,将从队列中取出的木棍再次入队
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
typedef pair<double,double> pdd;
double direction(pdd p1, pdd p2, pdd p3)//求向量的叉积
{
pdd d1 = make_pair(p3.first - p1.first, p3.second - p1.second);
pdd d2 = make_pair(p2.first - p1.first, p2.second - p1.second);
return d1.first*d2.second - d1.second*d2.first;
}
bool on_segment(pdd p1, pdd p2, pdd p3)//判断一条线段的端点是否在另一条线段上
{
double min_x = p1.first < p2.first ? p1.first : p2.first;
double max_x = p1.first > p2.first ? p1.first : p2.first;
if(min_x <= p3.first && p3.first <= max_x)//判断p3的x坐标是否在p1和p2之间
return true;
else
return false;
}
bool SegmentIntersect(pdd p1, pdd p2, pdd p3, pdd p4)
{
double d1 = direction(p1, p2, p3);
double d2 = direction(p1, p2, p4);
double d3 = direction(p3, p4, p1);
double d4 = direction(p3, p4, p2);
if(d1*d2 < 0 && d3*d4 < 0)
return true;
else if(d1 == 0 && on_segment(p1, p2, p3))
return true;
else if(d2 == 0 && on_segment(p1, p2, p4))
return true;
else if(d3 == 0 && on_segment(p3, p4, p1))
return true;
else if(d4 == 0 && on_segment(p3, p4, p2))
return true;
else
return false;
}
struct point
{
double x1,y1,x2,y2;
int id;
}s;
void solve(int n)
{
queue <point> q;
scanf("%lf%lf%lf%lf",&s.x1,&s.y1,&s.x2,&s.y2);
s.id = 1;
q.push(s);
for(int i = 2; i <= n; i ++)
{
scanf("%lf%lf%lf%lf",&s.x1,&s.y1,&s.x2,&s.y2);
s.id = i;
q.push(s);
while(!q.empty())
{
point tmp = q.front();
q.pop();
if(s.id == tmp.id)//队列中的所有元素都判断过了
{
q.push(s);
break;
}
pdd p1 = make_pair(s.x1, s.y1);
pdd p2 = make_pair(s.x2, s.y2);
pdd p3 = make_pair(tmp.x1, tmp.y1);
pdd p4 = make_pair(tmp.x2, tmp.y2);
if(!SegmentIntersect(p1,p2,p3,p4))//不交叉
{
q.push(tmp);
}
}
}
s = q.front(); q.pop();
printf("Top sticks: %d",s.id);
while(!q.empty())
{
s = q.front();
q.pop();
printf(", %d",s.id);
}
printf(".\n");
}
int main()
{
int n,i,j;
while(scanf("%d",&n),n)
{
solve(n);
}
return 0;
}