Poj2502 Subway

Poj2502

题目大意:首先给你两个坐标,一个是你家里的坐标,一个是你学校的坐标,然后接下来有若干条地铁线,每条地铁线上有若干个站点,给出每个站点的坐标,有这些点,这些点当中有距离,这个距离的单位是米,现在告诉你走路是10km/h,做地铁的话是40km/h,问你从家里到学校所花费的最短时间(分钟)

思路:建图比较麻烦,注意地铁站直接只能到达相邻的,并且算过权值之后还需要用步行的时间把所有节点间权值更新一遍。之后就是spfa

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#define inf 1e8
using namespace std;

const int maxn = 300 + 10;
double g[maxn][maxn], d[maxn];
struct Point{
    int x, y;
};
Point u, v, p[maxn];
int n, tot, sta[maxn], vis[maxn];
double dist(Point a, Point b){
    return sqrt( (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y) );
}

int ex(Point u){
    int i;
    for(i = 1; i < n; i++)
        if(p[i].x == u.x && p[i].y == u.y) break;
    if(i == n) p[n++] = u;
    return i;
}

void spfa(){
    queue<int> q;
    for(int i = 2; i <= n; i++)
        d[i] = inf;
    q.push(1);
    vis[1] = 1;
    int u;
    while(!q.empty()){
        u = q.front(); q.pop(); vis[u] = 0;
        for(int i = 1; i <= n; i++){
            if(d[i] > d[u] + g[u][i]){
                d[i] = d[u] + g[u][i];
                if(!vis[i]) {q.push(i); vis[i] = 1;}
            }
        }
    }
    printf("%d\n", (int)(d[2]+0.5));
}
int main(){
    freopen("poj2502.in", "r", stdin);
    Point u, v;
    for(int i = 1; i < maxn; i++)  
        for(int j = 1; j < maxn; j++)  
            if(i == j) g[i][j] = 0;  
            else g[i][j] = inf;  
    scanf("%d%d%d%d", &u.x, &u.y, &v.x, &v.y);
    n = 1; p[n++] = u; p[n++] = v;
    while(~scanf("%d%d", &u.x, &u.y)){
        tot = 0;
        sta[++tot] = ex(u);
        while(scanf("%d%d", &u.x, &u.y) && !(u.x == -1 && u.y == -1)){
            sta[++tot] = ex(u);
        }
        for(int i = 1; i < tot; i++){
            g[sta[i]][sta[i+1]] = g[sta[i+1]][sta[i]] = dist( p[sta[i]], p[sta[i+1]] )*3.0/2000.0;
        }
    }
    n--;
    for(int i = 1; i < n; i++){
        for(int j = i+1; j <= n; j++){
            g[i][j] = g[j][i] = min(g[i][j], dist(p[i], p[j])*3.0/500.0);
        }
    }
    spfa();
    return 0;
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值