您的位置:首页 > 其它

poj 1556 判线段相交+最短路问题

2013-08-16 01:33 337 查看
此题就是给出一幅图,然后上面一些墙,让求起点到终点的最短路径,说到最短路径那就必须得有一个图,那么首要问题就变成了如何构图,这里就得用到计算几何里面的基础知识,判断线段是否相交,也就是两点之间的连线,是否和墙相交,相交就没有路,不相交就有路,这样一来枚举任意两个点作判断便可成图,后面有图了就变成求最短路的问题,最近才学的,所以写两种吧,当作一种复习:

1.Dijkstra 求最短路:

#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<math.h>
#define INF 10000001.0

using namespace std;

struct Point{
double x;
double y;
}p[100],wall[100][2];
int n,vis[100];
double G[100][100],di[100];

double cross(Point a, Point b, Point c){
return  (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x);
}

bool intersect(Point a, Point b, Point c, Point d){
return  (max(a.x,b.x)>=min(c.x,d.x))&&
(max(a.y,b.y)>=min(c.y,d.y))&&
(min(a.x,b.x)<=max(c.x,d.x))&&
(min(a.y,b.y)<=max(c.y,d.y))&&
(cross(c,a,b)*cross(d,a,b)<0)&&
(cross(a,c,d)*cross(b,c,d)<0);
}

double dis(Point a, Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

int main(){
double a,b,c,d,e;
int num;
while(scanf("%d",&n)==1&&n!=-1){
num=4*n+1;//终点的下标
p[0].x=0, p[0].y=5;
p[num].x=10, p[num].y=5;
for(int i=0;i<n;i++){
scanf("%lf %lf %lf %lf %lf",&a,&b,&c,&d,&e);
wall[i*3][0].x=a;//相同横坐标总共三个墙,这是最下面一堵墙
wall[i*3][0].y=0;
wall[i*3][1].x=a;
wall[i*3][1].y=b;

wall[i*3+1][0].x=a;//第二堵墙
wall[i*3+1][0].y=c;
wall[i*3+1][1].x=a;
wall[i*3+1][1].y=d;

wall[i*3+2][0].x=a;//第三堵墙
wall[i*3+2][0].y=e;
wall[i*3+2][1].x=a;
wall[i*3+2][1].y=10;
//存一下点
p[i*4+1].x=p[i*4+2].x=p[i*4+3].x=p[i*4+4].x=a;
p[i*4+1].y=b,  p[i*4+2].y=c,  p[i*4+3].y=d,  p[i*4+4].y=e;
}
//开始建图
for(int i=0;i<=num;i++)//图的初始化,为使用Dijkstra算法作准备
for(int j=0;j<=num; j++) G[i][j] = (i==j ? 0 : INF);

for(int i=0; i<=num; i++){
for(int j=i+1; j<=num; j++){
int ok=1;
for(int k=0; k<n*3; k++){//检测是否和所有墙都不相交
if(p[i].x!=wall[k][0].x&&p[j].x!=wall[k][0].x&&p[i].x!=p[j].x&&intersect(p[i],p[j],wall[k][0],wall[k][1]))
{  ok=0; break; }
}
if(ok)G[i][j]=dis(p[i],p[j]);
}
}
//Dijstra求最短路
for(int i=0; i<=num; i++)di[i] = ( i==0 ? 0 : INF ) ;
memset(vis,0,sizeof(vis));
for(int i=0; i<=num; i++){
int x;
double m=INF;
for(int y=0; y<=num; y++)if(!vis[y]&&di[y]<=m)m = di[x=y];
vis[x]=1;
for(int y=0; y<=num; y++)if(!vis[y]&&G[x][y]!=INF&&di[x]+G[x][y]<di[y])
{   di[y]=di[x]+G[x][y]; }
}
printf("%.2lf\n",di[num]);
}
return 0;
}


2.Floyd:

#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<math.h>
#define INF 10000001.0

using namespace std;

struct Point{
double x;
double y;
}p[100],wall[100][2];
int n,vis[100];

double G[100][100],di[100][100];

const double eps = 1e-8;
int dlcmp (double x) {return x<-eps?-1:x>eps;}

double cross(Point a, Point b, Point c){
return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x);
}

bool intersect(Point a, Point b, Point c, Point d){
return (max(a.x,b.x)>=min(c.x,d.x))&&
(max(a.y,b.y)>=min(c.y,d.y))&&
(min(a.x,b.x)<=max(c.x,d.x))&&
(min(a.y,b.y)<=max(c.y,d.y))&&
(cross(c,a,b)*cross(d,a,b)<0)&&
(cross(a,c,d)*cross(b,c,d)<0);
}

double dis(Point a, Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

int main(){
double a,b,c,d,e;
int num;
while(scanf("%d",&n)==1&&n!=-1){
num=4*n+1;//终点的下标
p[0].x=0, p[0].y=5;
p[num].x=10, p[num].y=5;
for(int i=0;i<n;i++){
scanf("%lf %lf %lf %lf %lf",&a,&b,&c,&d,&e);
wall[i*3][0].x=a;//相同横坐标总共三个墙,这是最下面一堵墙
wall[i*3][0].y=0;
wall[i*3][1].x=a;
wall[i*3][1].y=b;

wall[i*3+1][0].x=a;//第二堵墙
wall[i*3+1][0].y=c;
wall[i*3+1][1].x=a;
wall[i*3+1][1].y=d;

wall[i*3+2][0].x=a;//第三堵墙
wall[i*3+2][0].y=e;
wall[i*3+2][1].x=a;
wall[i*3+2][1].y=10;
//存一下点
p[i*4+1].x=p[i*4+2].x=p[i*4+3].x=p[i*4+4].x=a;
p[i*4+1].y=b, p[i*4+2].y=c, p[i*4+3].y=d, p[i*4+4].y=e;
}
//开始建图
for(int i=0;i<=num;i++)//图的初始化,为使用Dijkstra算法作准备
for(int j=0;j<=num; j++) G[i][j] = (i==j ? 0 : INF);

for(int i=0; i<=num; i++){
for(int j=i+1; j<=num; j++){
int ok=1;
for(int k=0; k<n*3; k++){//检测是否和所有墙都不相交
if(p[i].x!=wall[k][0].x&&p[j].x!=wall[k][0].x&&p[i].x!=p[j].x&&intersect(p[i],p[j],wall[k][0],wall[k][1]))
{ ok=0; break; }
}
if(ok)G[i][j]=dis(p[i],p[j]);
}
}
//Floyd 求最短路
for(int i=0; i<=num; i++)
for(int j=0; j<=num; j++) di[i][j]= (i==j?0.0:INF);
for(int k=0; k<=num; k++)
for(int i=0; i<=num; i++)
for(int j=0; j<=num; j++)if(dlcmp(di[i][j]-di[i][k]-G[k][j])>0)
di[i][j]=di[i][k]+G[k][j];
printf("%.2lf\n",di[0][num]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息