poj1556 && nyoj227

本文提供了一道经典的最短路径问题——POJ1556的解决方案,通过判断线段是否相交来实现地图的构建,并采用Floyd算法求解两点间的最短距离。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接poj1556 && nyoj227

题意:从(0,5)点到(10,5)点的最近距离。
思路:可以转化成从起点到终点的最短路,这题放了好几天了,一直想不到怎么建图,今天终于想出来了。
考察线段相交。

AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#define ll long long
#define llu unsigned long long
using namespace std;
const double eps = 1e-6;
struct Point {
    double x,y;
    Point (double x = 0,double y = 0) : x(x),y(y) {}
};

Point p[150];

struct Line{
    Point a,b;
};

Line line[100];
int indl,indp;
double Map[150][150];
bool dcmp(double x) {
    if(fabs(x)-0.0 <= eps) return true;
    return false;
}
void init(){
    for(int i=1;i<=140; i++) {
        for(int j=1; j<=140; j++) Map[i][j] = 100000000.0;
//            Map[i][j] = (i!=j) ? 100000000.0 : 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));
}
double cross(Point a,Point b,Point c) {
    if(dcmp((b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y))) return 0;
    return ((b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y));
}
bool f(Point a,Point b,Point c,Point d) {
    if(min(a.x,b.x)<=max(c.x,d.x) && min(c.x,d.x)<=max(a.x,b.x)
       && min(a.y,b.y)<=max(c.y,d.y) && min(c.y,d.y)<=max(a.y,b.y)){
            if(cross(a,b,c)*cross(a,b,d) < 0 && cross(c,d,a)*cross(c,d,b) < 0) return true;
       }
    return false;
}
bool pd(Point x,Point y){
    for(int i=1; i<indl; i++) {
        if(f(x,y,line[i].a,line[i].b)) {
            return false;
        }
    }
    return true;
}
void jian(){
    for(int i=1;i<=indp; i++) {
        if(i == 1 || i == indp) {
            for(int j=1; j<=indp; j++) {
                if(i!=j && pd(p[i],p[j])) {
                    Map[i][j] = min(Map[i][j],dis(p[i],p[j]));
                }
            }
            continue;
        }
        for(int j=1; j<=indp; j++) {
            if(i != j && (((i-2)/4+1) != ((j-2)/4+1)) && pd(p[i],p[j])) {
                Map[i][j] = min(Map[i][j],dis(p[i],p[j]));
            }
        }
    }
}
int main(){
    int n;
    while(scanf("%d",&n)!=EOF) {
        if(n == -1) break;
        init();
        Point A,B;
        indl = 1,indp = 1;
        p[indp].x = 0, p[indp].y = 5;
        indp++;
        double a,b,c,d,e;
        for(int i=1;i<=n;i++) {
            scanf("%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e);
            p[indp].x = a; p[indp++].y = b;
            p[indp].x = a; p[indp++].y = c;
            p[indp].x = a; p[indp++].y = d;
            p[indp].x = a; p[indp++].y = e;
            A.x = a; A.y = 0;
            B.x = a; B.y = b;
            line[indl].a = A; line[indl++].b = B;
            A.x = a; A.y = c;
            B.x = a; B.y = d;
            line[indl].a = A; line[indl++].b = B;
            A.x = a; A.y = e;
            B.x = a; B.y = 10;
            line[indl].a = A; line[indl++].b = B;
        }
        p[indp].x = 10; p[indp].y = 5;
        jian();  //建图
        // 最短路
        for(int k=1; k<=indp; k++) {
            for(int i=1; i<=indp; i++) {
                for(int j=1; j<=indp; j++) {
                    if(Map[i][k]!=100000000.0 && Map[k][j] != 100000000.0) {
                        Map[i][j] = min(Map[i][j],Map[i][k]+Map[k][j]);
                    }
                }
            }
        }
        printf("%.2lf\n",Map[1][indp]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值