POJ2653 Pick-up sticks 线段相交

题目大意:有n个木棒(可视为线段),随机扔到平面坐标系中,问你有哪些木棒上面没有压其他的木棒。

典型的求线段相交的问题,把输入的木棒视为线段,分别看该木棒后面的木棒中有没有和他相交的。还有就是本题的时间卡的比较少,O(n^2)的复杂度都有可能爆。刚开始我是按正序判断的,即找出当前木棒前面的木棒中有没有和他相交的,这样一来就做了很多的无用功,比如第一根木棒和第二根木棒相交了,我们已经标记了第一根木棒,那么我们在看第三根木棒时又把第一根木棒拿来比较了一次,这样一来就会重复标记很多次木棒,提交结果很显然TLE。后来换了一种思维,我们对于某根木棒,只需看她后面的木棒中有没有和他相交的,如果有,则标记该木棒,同时跳出这层循环,这样时间上就很少有浪费了。

代码如下:

#include <cstdio>
#include <algorithm>
#define MAX 100010
using namespace std;
typedef struct node
{
    double x,y;
}Point;
typedef struct line
{
    Point start,end;
    bool flag;
}vector;
vector stick[MAX];
double multi(Point p1,Point p2,Point p0)
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
bool cross(vector v1,vector v2)
{
    if(max(v1.start.x,v1.end.x)>=min(v2.start.x,v2.end.x)&&max(v2.start.x,v2.end.x)>=min(v1.start.x,v1.end.x)&&max(v1.start.y,v1.end.y)>=min(v2.start.y,v2.end.y)&&multi(v2.start,v1.end,v1.start)*multi(v1.end,v2.end,v1.start)>=0&&multi(v1.start,v2.end,v2.start)*multi(v2.end,v1.end,v2.start)>=0)
      return true;
    return false;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1&&n)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf%lf",&stick[i].start.x,&stick[i].start.y,&stick[i].end.x,&stick[i].end.y);
            stick[i].flag=true;
        }
        for(int i=1;i<n;i++)
          for(int j=i+1;j<=n;j++)
            if(cross(stick[i],stick[j]))
            {
                stick[i].flag=false;
                break;
            }
        bool tmp=true;
        printf("Top sticks: ");
        for(int i=1;i<=n;i++)
          if(stick[i].flag&&tmp)
          {
              printf("%d",i);
              tmp=false;
          }
          else if(stick[i].flag)
            printf(", %d",i);
        printf(".\n");
    }
    return 0;
}


你可能感兴趣的:(POJ2653 Pick-up sticks 线段相交)