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;
}
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;
}
相关文章推荐
- poj1556 判断线段相交+最短路
- POJ 1556 The Doors 判断线段相交+最短路
- POJ 1556 The Doors(判断线段相交 && 最短路)
- POJ 1556 计算几何 判断线段相交 最短路
- POJ1556---The Doors (计算几何基础:判断线段相交(快速排斥实验+跨立实验))
- POJ1556 The Doors(线段与线段相交 + 最短路
- poj 1556 The Doors(最短路+判断线段相交)
- poj 1556 The Doors(最短路+判断线段相交)
- poj 1556 The Doors 线段相交判断+最短路
- POJ 1556 The Doors 最短路floyd + 判断两线段相交
- HLG 1450 Farmer John【线段相交判断+最短路】
- POJ 1556 The Doors 最短路floyd + 判断两线段相交
- POJ-1556 线段相交的判断与最短路(几何+图论)
- poj 1556 计算几何(判断线段相交+建图)+最短路
- POJ1556(最短路+线段相交)
- POJ_1556_The Doors_判断线段相交+最短路
- 【POJ】1556 The Doors 最短路+判断线段相交
- POJ 1556 The Doors (计算几何判断线段相交+最短路)
- The Doors--poj1556(最短路+判断点与线段的关系)
- POJ 1556 The Doors(判断线段相交 && 最短路)