洛谷P1266 速度限制

题目链接:https://www.luogu.org/problem/show?pid=1266

解题思路:
1.求最快路线类似于求最短路,想到用spfa解决。
2.和一般的spfa不同,本题的路径中是以距离/速度来更新答案的,并且速度存在两种情况,需要分别分析。
3.既然有了速度这个变量,我们需要用数组来储存记录速度,dis[i][j]表示从到i点时速度为j的最快路线。在更新最短路的时候判断一下速度是否为0,用不同的速度更新答案。
4.题目要求输出路径,需要记录点和速度,递归输出路径。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define pr pair<int,int>
using namespace std;
queue<pair<int,int> >q;
struct node{
    int from,to,t,ds;
}list[505*505];
double dis[505][505];
bool v[255][505];
int n,m,k,s,ans,x,y,t,z,head[255],px[255][505],ps[255][505];
void add(int x,int y,int t,int z){
    list[++s].from=head[x];
    list[s].to=y;
    list[s].t=t;
    list[s].ds=z;
    head[x]=s;
}
void spfa(){
    memset(dis,66,sizeof dis);
    v[1][70]=1;q.push(pr(1,70));dis[1][70]=0;
    while(!q.empty()){
        pr p=q.front();q.pop();
        int x=p.first,y=p.second;v[x][y]=0;
        for (int i=head[x];i;i=list[i].from){

        if (list[i].t==0)
         {
            if (dis[list[i].to][y]>dis[x][y]+1.0*list[i].ds/y){
            dis[list[i].to][y]=dis[x][y]+1.0*list[i].ds/y;
            px[list[i].to][y]=x;
            ps[list[i].to][y]=y;
            if (!v[list[i].to][y]){
                v[list[i].to][y]=1;
                q.push(pr(list[i].to,y));
            }
             }
         }
         else {
         int sp=list[i].t;
         if (dis[list[i].to][sp]>dis[x][y]+1.0*list[i].ds/sp){
            dis[list[i].to][sp]=dis[x][y]+1.0*list[i].ds/sp;
            px[list[i].to][sp]=x;
            ps[list[i].to][sp]=y;
            if (!v[list[i].to][sp]){
                v[list[i].to][sp]=1;
                q.push(pr(list[i].to,sp));
            }
         }
         }
    }
}
}
void print(int a,int b)
{
    if(a!=1)print(px[a][b],ps[a][b]);
    printf("%d ",a-1);
}
int main(){
    cin>>n>>m>>k;k++; 
    for (int i=1;i<=m;i++){
        scanf("%d%d%d%d",&x,&y,&t,&z);
        x++;y++;
        add(x,y,t,z);
    }
    spfa();
    double ans=1e30;int c;
    for (int i=1;i<=500;i++){
        if (ans>dis[k][i])
         ans=dis[k][i],c=i;
    }
    print(px[k][c],ps[k][c]);
    cout<<k-1;
    return 0;
}
以下是使用Dijkstra算法求解的C++代码示例: ```cpp #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> using namespace std; const int MAXN = 205; const double INF = 1e9; struct Point { double x, y; }; struct Edge { int from, to; double dist; }; struct HeapNode { int u; double d; bool operator < (const HeapNode& rhs) const { return d > rhs.d; } }; int n, m; Point p[MAXN]; Edge e[MAXN * MAXN]; int first[MAXN], next[MAXN * MAXN]; double dist[MAXN][MAXN]; bool vis[MAXN]; void addEdge(int u, int v, double w) { static int cnt = 0; e[cnt].from = u; e[cnt].to = v; e[cnt].dist = w; next[cnt] = first[u]; first[u] = cnt++; } void Dijkstra(int s) { priority_queue<HeapNode> pq; memset(vis, false, sizeof(vis)); for (int i = 0; i < n; i++) { dist[s][i] = (i == s ? 0 : INF); } pq.push((HeapNode){s, 0}); while (!pq.empty()) { int u = pq.top().u; pq.pop(); if (vis[u]) continue; vis[u] = true; for (int i = first[u]; i != -1; i = next[i]) { int v = e[i].to; double w = e[i].dist; if (dist[s][v] > dist[s][u] + w) { dist[s][v] = dist[s][u] + w; if (!vis[v]) pq.push((HeapNode){v, dist[s][v]}); } } } } int main() { memset(first, -1, sizeof(first)); scanf("%lf%lf", &p[0].x, &p[0].y); n = 1; while (scanf("%lf%lf%lf%lf", &p[n].x, &p[n].y, &p[n + 1].x, &p[n + 1].y) == 4) { double d = sqrt(pow(p[n].x - p[n + 1].x, 2) + pow(p[n].y - p[n + 1].y, 2)); addEdge(n, n + 1, d / 50); addEdge(n + 1, n, d / 50); n += 2; } m = n; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { double d = sqrt(pow(p[i].x - p[j].x, 2) + pow(p[i].y - p[j].y, 2)); if (i % 2 == 0 && j % 2 == 0) { addEdge(i, j + 1, d / 20); addEdge(j, i + 1, d / 20); } else if (i % 2 == 0 && j % 2 == 1) { addEdge(i, j, d / 50); addEdge(j + 1, i + 1, d / 50); } else if (i % 2 == 1 && j % 2 == 0) { addEdge(i + 1, j + 1, d / 50); addEdge(j, i, d / 50); } else { addEdge(i + 1, j, d / 20); addEdge(j + 1, i, d / 20); } } } for (int i = 0; i < n; i++) { Dijkstra(i); } double ans = INF; for (int i = 0; i < n; i++) { double dist1 = 0; for (int j = 0; j < n; j++) { dist1 = max(dist1, dist[i][j]); } ans = min(ans, dist1); } int h = (int)floor(ans); int m = (int)floor((ans - h) * 60); printf("%d:%02d\n", h, m); return 0; } ``` 注:该代码在上能够通过本题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值