您的位置:首页 > 其它

Poj1556线段相交判断+动规最短路

2012-07-19 17:39 183 查看
  最近在SIAT做自己非常感兴趣的流动数据分析。做3D和纯开发久了,发现计算几何和图论的算法都稍微有点生疏,趁最近还不忙,刷几道相关的题目上下手当作复习。

  poj1556,感觉这题算是计算几何题目里面的一个很经典的解体思路,最优值往往会离散在某些极限点上。就跟这题目一样,如果能够直接连接两点,ok;否则最短路径一定会经过中间墙上的四个点中某个点(可以自己枚举下几种情况)。剩下就用了Floyd的类似思想,看点i和点j的最短路径,如果i点能够直线连接j点,那么直接输出最短路径,否则就迭代看点i到点k的最短路径+点k到点j的最短路径哪个最优。

#include<iostream>
#include <math.h>
using namespace std;

const double MAXVALUE=(double)(1<<30);

double MinNumber(double x,double y)
{
if(x<y)
{
return x;
}
else
{
return y;
}
}

double MaxNumber(double x,double y)
{
if(x<y)
{
return y;
}
else
{
return x;
}
}

class Point
{
public:
Point(){}
Point(double tx,double ty)
{
x=tx;
y=ty;
}
double x,y;
};

class Segment
{
public:
Segment(){}
Segment(Point p1,Point p2)
{
point1=p1;
point2=p2;
}
Point point1,point2;
};

class Wall
{
public:
double x;
double y[4];
int iPointNum;
};

double Distance(Point point1,Point point2)
{
return sqrt( pow(point1.x-point2.x,2) + pow(point1.y-point2.y,2) );
}

//return (p2-p1)*(p3-p1)
double Direction(Point point1,Point point2,Point point3)
{
Point vec1=Point(point2.x-point1.x,point2.y-point1.y);
Point vec2=Point(point3.x-point1.x,point3.y-point1.y);
return (vec1.x*vec2.y-vec1.y*vec2.x) ;
}

bool OnSegment(Point point,Segment seg)
{
double minX=MinNumber(seg.point1.x,seg.point2.x);
double maxX=MaxNumber(seg.point1.x,seg.point2.x);

double minY=MinNumber(seg.point1.y,seg.point2.y);
double maxY=MaxNumber(seg.point1.y,seg.point2.y);

if(point.x>=minX && point.x<=maxX && point.y>=minY && point.y<=maxY)
{
return true;
}
else
{
return false;
}
}
//线段相交测试主函数
bool SegmentInteract(Segment seg1,Segment seg2)
{
//seg2 cross seg1
double d1=Direction(seg1.point1,seg1.point2,seg2.point1);
double d2=Direction(seg1.point1,seg1.point2,seg2.point2);

//seg1 cross seg2
double d3=Direction(seg2.point1,seg2.point2,seg1.point1);
double d4=Direction(seg2.point1,seg2.point2,seg1.point2);

if( d1*d2<0 && d3*d4<0 )
return true;

else if(d1==0 && OnSegment(seg2.point1,seg1))
{
return true;
}

else if(d2==0 && OnSegment(seg2.point2,seg1))
{
return true;
}

else if(d3==0 && OnSegment(seg1.point1,seg2))
{
return true;
}

else if(d4==0 && OnSegment(seg1.point2,seg2))
{
return true;
}

return false;
}

//See if the seg interact with any of the walls[iStart]...........walls[iEnd]
bool InteractWalls(int iStart,int iEnd,Wall walls[], Segment seg)
{
if(iStart>iEnd)
{
return false;
}

for(int i=iStart;i<=iEnd;i++)
{
bool virtualInteract=false;
for(int j=0;j<4;j+=2)
{
if(SegmentInteract(Segment(Point(walls[i].x,walls[i].y[j]),Point(walls[i].x,walls[i].y[j+1])),seg))
{
//interact with a virtual segment, so ok.
virtualInteract=true;
}
}

if(virtualInteract==false)//the seg interacts with this wall.
{
return true;
}
}

return false;
}

int main()
{

Wall walls[20];
Point startPoint=Point(0.0f,5.0f);
Point endPoint=Point(10.0f,5.0f);
int nInterWall=0;
int nPointNumber=0;
double minDistance[100][100];

while(cin>>nInterWall)
{
if(nInterWall==-1)
return 0;

nPointNumber=4*nInterWall+2;

//Initialize the first and last wall
walls[0].iPointNum=1;
walls[0].x=0.0f;
walls[0].y[0]=5.0f;

walls[nInterWall+1].iPointNum=1;
walls[nInterWall+1].x=10.0f;
walls[nInterWall+1].y[0]=5.0f;

//Initialize the inter walls whose index start from 1.
for(int i=1;i<=nInterWall;i++)
{
cin>>walls[i].x;
for(int j=0;j<4;j++)
cin>>walls[i].y[j];
walls[i].iPointNum=4;
}

//initialize the distance matrix
for(int i=0;i<nPointNumber;i++)
{
for(int j=0;j<nPointNumber;j++)
{
minDistance[i][j]=MAXVALUE;
}
}

for(int iInterNumber=0;iInterNumber<=nInterWall;iInterNumber++)
{
for(int istartIndex=0;istartIndex<nInterWall+2-1-iInterNumber;istartIndex++)
{
int igoalIndex=istartIndex+iInterNumber+1;
//iterate the four points of start wall and goal wall.
for(int i=0;i<walls[istartIndex].iPointNum;i++)
for(int j=0;j<walls[igoalIndex].iPointNum;j++)
{
int sPointIndex=(istartIndex==0)?0:4*(istartIndex-1)+i+1;
int ePointIndex=4*(igoalIndex-1)+j+1;

if(InteractWalls(istartIndex+1,igoalIndex-1,walls,Segment(Point(walls[istartIndex].x,walls[istartIndex].y[i]),Point(walls[igoalIndex].x,walls[igoalIndex].y[j]))))
{
for(int iWallk=istartIndex+1;iWallk<igoalIndex;iWallk++)//iterate the inter walls between the two goal walls.
{
for(int iPointj=0;iPointj<4;iPointj++)//go over the four points of walls iWallk
{
int tmpPointIndex=4*(iWallk-1)+iPointj+1;
double tmpDis=minDistance[sPointIndex][tmpPointIndex]+minDistance[tmpPointIndex][ePointIndex];
if(tmpDis<minDistance[sPointIndex][ePointIndex])
{
minDistance[sPointIndex][ePointIndex]=tmpDis;
}
}
}
}
else
{
minDistance[sPointIndex][ePointIndex]=Distance(Point(walls[istartIndex].x,walls[istartIndex].y[i]),Point(walls[igoalIndex].x,walls[igoalIndex].y[j]));
}
}
}
}
//cout<<setprecision(2)<<minDistance[0][4*nInterWall+1]<<endl;
printf("%.2f\n",minDistance[0][4*nInterWall+1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息