题目大意:有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;
}