poj 1556 判线段相交+最短路问题
2013-08-16 01:33
337 查看
此题就是给出一幅图,然后上面一些墙,让求起点到终点的最短路径,说到最短路径那就必须得有一个图,那么首要问题就变成了如何构图,这里就得用到计算几何里面的基础知识,判断线段是否相交,也就是两点之间的连线,是否和墙相交,相交就没有路,不相交就有路,这样一来枚举任意两个点作判断便可成图,后面有图了就变成求最短路的问题,最近才学的,所以写两种吧,当作一种复习:
1.Dijkstra 求最短路:
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;
}
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;
}
相关文章推荐
- poj 2074 Line of Sight(视线问题,求直线与线段的交点及判断相交)
- POJ 2074 线段相交 视线问题
- 【解题报告】 POJ 1556 The Doors -- 最短路问题 Dijkstra算法 + 直线相交
- poj 2826 An Easy Problem?! (线段相交问题终极版...并不easy)
- poj 2826(好坑,线段相交问题)
- POJ 1039 Pipe(计算几何---直线和线段的相交问题)
- POJ2653(Pick-up sticks)(线段相交问题)
- POJ 2653 Pick-up sticks 线段相交问题
- POJ 1556 线段相交于最短路——几何问题转换为图问题
- POJ 2653 Pick-up sticks 线段相交问题
- POJ 3347 Kadj Squares 复杂的线段相交问题。这个题目是计算几何的扩大数据运算的典型应用 有时候扩大数据范围避免浮点误差,这个题就是应用
- poj 1556 线段相交+最短路
- poj 2653(线段相交)
- POJ 1039 Pipe (计算几何、思维、线段相交)
- POJ 3304 直线和线段相交
- poj 2653 Pick-up sticks(判断线段相交)
- 简单几何(线段相交)+模拟 POJ 3449 Geometric Shapes
- POJ 2653 Pick-up sticks 判断线段相交
- nyoj 1132 promise me a medal(线段相交问题)
- The Doors - POJ 1556 (线段相交)