CodeForces 589M Taxi in Berland 最短路

题意:给你一个W×L的网格,有一个起点和一个终点,你在起点的速度是零,加速度是a,有一些点有速度限制vp,全程有一个最大速度限制vm,问你从起点到终点的最短时间是多少。

思路:由于从起点到终点要不直接到达,要不经过一些限速点,所以预处理出起点和其他限速点直接相邻的点,建图,跑最短路即可。两点之间的最短时间用高中物理的知识可以解决。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <vector>
using namespace std;

const int maxn = 100 + 10;
const int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
const int INF = 0x3f3f3f3f;
const int maxe = 20000 + 100;
const double eps = 1e-8;
typedef pair<int, int> pill;
struct Edge{
    int v, next;
    double d;
    Edge(int v = 0, double d = 0, int next = 0) : v(v), d(d), next(next) {}
};
struct HeapNode{
    int v;
    double min_time;
    HeapNode(int v, double min_time) : v(v), min_time(min_time) {}
    HeapNode() {}
    bool operator < (const HeapNode &rhs) const{
        return min_time > rhs.min_time;
    }
};
int n, W, L;
double a, vm, vp;
pill pos[maxn];
int vis[maxn][maxn];//0 st 1 ed >=2 police
int vis2[maxn][maxn];
vector<int> neighbor;
int d[maxn], Head[maxn], cntE;
Edge edge[maxe];
bool judge(int x, int y){
    if(x >= 0 && x <= W && y >= 0 && y <= L)
        return true;
    return false;
}
struct Work{
    int x, y;
    int step;
    Work(int x, int y, int step) : x(x), y(y), step(step) {}
    Work() {}
};
void bfs(int x, int y, int cu){
    Work st(x, y, 0);
    queue<Work> Q;
    Q.push(st);
    d[cu] = 0;
    while(!Q.empty()){
        Work cur = Q.front(); Q.pop();
        int xx = cur.x;
        int yy = cur.y;
        if(vis2[xx][yy]) continue;
        vis2[xx][yy] = 1;
        int step = cur.step;
        if(vis[xx][yy] && vis[xx][yy] != cu){
            d[vis[xx][yy]] = step;
            neighbor.push_back(vis[xx][yy]);
            continue;
        }
        for(int i = 0; i < 4; i++){
            int dx = xx + dir[i][0];
            int dy = yy + dir[i][1];
            if(!judge(dx, dy) || vis2[dx][dy]) continue;
                Q.push(Work(dx, dy, step + 1));
        }
    }
}
void init(){
    memset(Head, -1, sizeof(Head));
    cntE = 0;
}
void add(int u, int v, int d){
    edge[cntE] = Edge(v, double(d), Head[u]);
    Head[u] = cntE++;
}
double get_time(double v0, double vt, double s, double &vf){
    double t1 = (vt - v0) / a;
    if(v0 * t1 + a * t1 * t1 / 2 >= s){
        double ans = (sqrt(v0 * v0 + 2 * a * s) - v0) / a;
        vf = v0 + a * ans;
        return ans;
    }
    else{
        double len = (2 * vm * vm - v0 * v0 - vt * vt) / 2 / a, vx;
        vf = vt;
        if(len > s){
            vx = sqrt((2 * a * s + v0 * v0 + vt * vt) / 2);
            return (2 * vx - v0 - vt) / a;
        }
        else{
            return (2  * vm - v0 - vt) / a + (s - (2 * vm * vm - v0 * v0 - vt * vt) / 2 / a) / vm;
        }
    }
}
double dist[maxn], cur_v[maxn];
void dijkstra(){
    double ddd;
    for(int i = 0; i < n + 3; i++) dist[i] = double(INF);
    dist[1] = 0;
    priority_queue<HeapNode> Q;
    Q.push(HeapNode(1, 0));
    while(!Q.empty()){
        HeapNode cur = Q.top(); Q.pop();
        int u = cur.v;
        double t = cur.min_time;
        for(int i = Head[u]; ~i; i = edge[i].next){
            int v = edge[i].v;
            double v0, vt, vf;
            v0 = cur_v[u];
            if(v > 2) vt = vp;//is police
            else vt = vm;
            double tt = get_time(v0, vt, edge[i].d, vf);
            if(dist[v] > dist[u] + tt){
                dist[v] = dist[u] + tt;
                cur_v[v] = vf;
                Q.push(HeapNode(v, dist[v]));
            }
        }
    }
}
int main()
{
    scanf("%d%d%d%lf%lf%lf", &W, &L, &n, &a, &vm, &vp);
    if(vm < vp) vp = vm;
    scanf("%d%d%d%d", &pos[1].first, &pos[1].second, &pos[2].first, &pos[2].second);
    vis[pos[1].first][pos[1].second] = 1;
    vis[pos[2].first][pos[2].second] = 2;
    for(int i = 3; i < n + 3; i++){
        int x, y;
        scanf("%d%d", &x, &y);
        pos[i].first = x;
        pos[i].second = y;
        vis[x][y] = i;
    }
    init();
    for(int i = 1; i < n + 3; i++){
        int x = pos[i].first;
        int y = pos[i].second;
        memset(vis2, 0, sizeof(vis2));
        memset(d, INF, sizeof(d));
        neighbor.clear();
        bfs(x, y, i);
        for(int j = 0; j < (int)neighbor.size(); j++){
            add(i, neighbor[j], d[neighbor[j]]);
        }
    }
    dijkstra();
    printf("%.10lf\n", dist[2]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值