代码改变世界

POJ 2653 Pick-up sticks

2012-03-28 10:19  咆哮的马甲  阅读(207)  评论(0编辑  收藏  举报

考察点在于如何判断两线段相交(快速排斥+跨立),之前使用链表结构超时了,后来用vector实现。

 

判断线段相交的办法,这篇文章讲的很明白。http://324012406.iteye.com/blog/738318

 

#include <iostream>
#include <vector>

using namespace std;

typedef struct Coordinate
{
Coordinate(double _x, double _y)
:x(_x),y(_y)
{
}

double x;
double y;
} Coordinate;

typedef struct Stick
{
Stick()
:index(0),start(0.0,0.0),end(0.0,0.0)
{
}

Stick(int i, double x1, double y1, double x2, double y2)
:index(i),start(x1,y1),end(x2,y2)
{
}

int index;
Coordinate start;
Coordinate end;
} Stick;


inline bool isRectCrossed(const Stick& s1,const Stick& s2)
{
// rect1
double rect1_min_x = min(s1.start.x,s1.end.x);
double rect1_max_x = max(s1.start.x,s1.end.x);
double rect1_min_y = min(s1.start.y,s1.end.y);
double rect1_max_y = max(s1.start.y,s2.end.y);

// rect2
double rect2_min_x = min(s2.start.x,s2.end.x);
double rect2_max_x = max(s2.start.x,s2.end.x);
double rect2_min_y = min(s2.start.y,s2.end.y);
double rect2_max_y = max(s2.start.y,s2.end.y);

// innerRect of rect1 and rect2
double innerRect_min_x = max(rect1_min_x,rect2_min_x);
double innerRect_max_x = min(rect1_max_x,rect2_max_x);

if(innerRect_min_x > innerRect_max_x)
return false;

double innerRect_min_y = max(rect1_min_y,rect2_min_y);
double innerRect_max_y = min(rect1_max_y,rect2_max_y);

if(innerRect_min_y > innerRect_max_y)
return false;

return true;
}

inline double CrossProduct(const Coordinate& c1,const Coordinate& c2)
{
return c1.x*c2.y-c2.x*c1.y;
}

inline bool isCrossed(const Stick& s1,const Stick& s2)
{
if(!isRectCrossed(s1,s2))
return false;

if(CrossProduct(Coordinate(s1.start.x-s2.start.x,s1.start.y-s2.start.y),Coordinate(s2.end.x-s2.start.x,s2.end.y-s2.start.y))*CrossProduct(Coordinate(s2.end.x-s2.start.x,s2.end.y-s2.start.y),Coordinate(s1.end.x-s2.start.x,s1.end.y-s2.start.y))>=0 &&
CrossProduct(Coordinate(s2.start.x-s1.start.x,s2.start.y-s1.start.y),Coordinate(s1.end.x-s1.start.x,s1.end.y-s1.start.y))*CrossProduct(Coordinate(s1.end.x-s1.start.x,s1.end.y-s1.start.y),Coordinate(s2.end.x-s1.start.x,s2.end.y-s1.start.y))>=0 )
return true;

return false;
}


int main()
{
vector<Stick> vecStick;
vecStick.push_back(Stick()); //Not use the first one.
while(1)
{
int n = 0;
scanf("%d",&n);

if(n == 0)
break;

for(int i =1; i<=n; i++)
{
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);

vecStick.push_back(Stick(i,x1,y1,x2,y2));
}

bool firstFlag = true;
for(int i =1; i<n; i++)
{
bool crossed = false;
for(int j = i+1; j<=n; j++)
{
if(isCrossed(vecStick[i],vecStick[j]))
{
crossed = true;
break;
}
}

if(!crossed)
{
if(firstFlag)
{
printf("Top sticks: %d",i);
firstFlag = false;
}
else
{
printf(", %d",i);
}
}
}

printf(", %d.\n",n);
vecStick.clear();
vecStick.push_back(Stick()); //Not use the first one.
}

return 0;
}