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

17 篇文章 0 订阅
10 篇文章 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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值