zoukankan      html  css  js  c++  java
  • POJ 2267 From Dusk till Dawn or: Vladimir the Vampire(最短路变形)

    题意:

    有一个吸血鬼要旅游, 他只能在晚上6点到第二天凌晨6点行动(18:00 ~ 6:00), 然后每天中午12点要喝1L的血(12:00), 现有m条火车的发车时间行程时间, 问他从a到达b需要喝多少升的血。

    分析:

    根据发车时间和题意, 可以把发车时间 < 18的排除掉, 然后行程时间 > 6的排除掉, 我们可以把一天看成30小时, 加起来大于30的都排除掉。

    然后以血量为花费进行最短路, 如果能在同一天换乘的话, 血量花费为0, 否则为1。

    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i,a,b) for(int i = a; i < b; i++)
    #define _rep(i,a,b) for(int i = a; i <= b; i++)
    const int maxn = 107;
    const int inf = 1e9;
    struct edge{
        int to, st, end_time;
        edge(int _to,int _st,int _end_time): to(_to) ,st(_st), end_time(_end_time){}
    };
    struct node{
        int to, arr_time; //到达城市, 到达时间
        node(int _to, int _arr_time): to(_to) , arr_time(_arr_time){}
    };
    vector<edge> G[maxn];
    map<string , int> id;
    int city_cnt, m;
    
    void init(){
        for(int i = 0; i < maxn; i++) G[i].clear();
        id.clear();
        city_cnt = 0;
    }
    void s2i(string s){//把城市名称映射成数字
        if(!id.count(s)) id[s] = city_cnt++;
    }
    
    int spfa(int from, int to){
        int dis[maxn][30 + 7]; //dis[i][j]代表在j点到达i城市需要最少血量
        bool vis[maxn][30 + 7];//代表[i][j](j点到达i城市需要最少血量)在不在队列中
        rep(i,0,city_cnt) _rep(j,18,30) dis[i][j] = inf;
        memset(vis, 0 , sizeof(vis));
        queue<node> q;
        _rep(i,18,30){
            vis[from][i] = 1;
            dis[from][i] = 0;
            q.push(node(from,i));
        }
        while(!q.empty()){
            node f = q.front();
            int u = f.to, t = f.arr_time;
            rep(i,0,G[u].size()){
                int st_time = G[u][i].st, v = G[u][i].to, ed_time = G[u][i].end_time;
                if(t <= st_time){//在同一天可以赶上这趟火车
    
                    if(dis[v][ed_time] > dis[u][t]){ //不需要带1L血
                        dis[v][ed_time] = dis[u][t];
                        if(!vis[v][ed_time]){
                            vis[v][ed_time] = 1;
    //                        printf("same day
    ");
                            q.push(node(v,ed_time));
                        }
                    }
                }
                else //同一天赶不上这趟火车, 需要带上1L血
                {
                    if(dis[v][ed_time] > dis[u][t] + 1) //这个+1就是1L血
                    {
                        dis[v][ed_time] = dis[u][t] + 1;
                        if(!vis[v][ed_time]){
                            vis[v][ed_time] = 1;
                            q.push(node(v, ed_time));
                        }
                    }
                }
            }
            vis[u][t] = 0;
            q.pop();
        }
        int min_dis = inf;
        _rep(i,18,30){//枚举目标城市每个到达时间的最少血量, 选最少的一个为答案
            min_dis = min(min_dis, dis[to][i]);
        }
        return min_dis;
    }
    int main(){
        int T, kase = 1;
        cin >> T;
        while(T--){
            init();
            string from, to;
            cin >> m;
            rep(i,0,m){
                string u , v;
                int st, dur;
                cin >> u >> v >> st >> dur;
                s2i(u),s2i(v);
                if(st <= 6) st += 24;//如果起始时间小于6, 那么当24 + st小时算
                if(!(st >= 18 && st + dur <= 30)) continue; //总时间小于30, 起始时间大于18都是符合题意的。
                G[id[u]].push_back(edge(id[v],st, st + dur));
            }
            cin >> from >> to;
            s2i(from),s2i(to);
            cout << "Test Case " << kase++ <<".
    ";
            int blood = spfa(id[from], id[to]);
            if(blood == inf){
                cout << "There is no route Vladimir can take.
    ";
            }else{
                cout << "Vladimir needs " << blood << " litre(s) of blood.
    ";
            }
        }
    }
  • 相关阅读:
    面试代码基础(一)从strstr说起
    面试笔试总结(二)之 C++基础
    面试笔试总结(一)之 C++基础
    HMM代码实践
    计算两篇文章相似度代码
    主题模型
    mysql5.6.34-debug Source distribution在树莓派下编译的几个错误
    windows守护进程脚本
    fastcgi模式下设置php最大执行时间
    mysql基础知识笔记
  • 原文地址:https://www.cnblogs.com/Jadon97/p/8341570.html
Copyright © 2011-2022 走看看