zoukankan      html  css  js  c++  java
  • [ZJOI2006] 物流运输

    [ZJOI2006] 物流运输

    题目大意:连续(n)天在一个图上走最短路,但是每个点有一定时间不开放,改变路线要加大花费,在图上走也需要花费,求最小花费。

    Solution

    计算出某天到某天的最短路,进行(dp)

    • 状态(f[i])表示到第(i)天的最小花费
    • 转移方程(f[i] = min{dis[1][i] cdot i, f[j - 1] + dis[j][i] cdot (i - j + 1) + k (1<j leq i)})

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    
    const int Maxm = 25;
    const int Maxn = 105;
    const int INF = 1e9;
    
    struct Edge{
        int to, next, len;
    }e[20005];
    
    int n, m, qwq, k, d, cnt, head[Maxm], ban[Maxm][Maxn], vis[Maxm], f[Maxn], dist[Maxn][Maxn], dis[Maxm];
    
    inline void addedge(int x, int y, int z){
        ++cnt;
        e[cnt].to = y;
        e[cnt].next = head[x];
        e[cnt].len = z;
        head[x] = cnt;
    }
    
    inline int SPFA(int x, int y){
        memset(dis, 0x3f, sizeof(dis));
        memset(vis, 0, sizeof(vis));
        std::queue <int> q;
        q.push(1);
        dis[1] = 0;
        vis[1] = 1;
        int u, v;
        for(int i = 1; i <= m; ++i){
            for(int j = x; j <= y; ++j){
                if(ban[i][j]){
                    vis[i] = 1;
                    break;
                }
            } 
        } 
        while(!q.empty()){
            
            u = q.front();
            q.pop();
            vis[u] = 0;
            for(int i = head[u]; i; i = e[i].next){
                v = e[i].to;
                if(dis[v] > dis[u] + e[i].len){
                    dis[v] = dis[u] + e[i].len;
                    if(!vis[v]){
                        q.push(v);
                        vis[v] = 1;
                    }
                }
            }
        }
        return dis[m];
    }
    
    int main(){
        scanf("%d %d %d %d", &n, &m, &k, &qwq);
        for(int i = 1, la, lb, lc; i <= qwq; ++i){
            scanf("%d %d %d", &la, &lb, &lc);
            addedge(la, lb, lc);
            addedge(lb, la, lc);
        }//输入连接的边
        scanf("%d", &d);
        for(int i = 1, la, lb, lc; i <= d; ++i){
            scanf("%d %d %d", &la, &lb, &lc);
            for(int j = lb; j <= lc; ++j){
                ban[la][j] = 1;
            }
        }//ban表示第la个码头第j天是否被禁止运输了
    
        for(int i = 1; i <= n; ++i)
            for(int j = i; j <= n; ++j){
                dist[i][j] = SPFA(i, j);
            }//计算某一天到某一天的最短距离
    
        for(int i = 1; i <= n; ++i){
            if(dist[1][i] < 1061109567)
                f[i] = dist[1][i] * i;//不改变航线
            else 
                f[i] = INF; 
            for(int j = 1; j <= i; ++j){
                if(dist[j][i] < 1061109567)
                f[i] = std::min(f[i], f[j - 1] + dist[j][i] * (i - j + 1) + k);
            }//枚举上一次改变航线的日期
        }
        printf("%d
    ", f[n]);
        return 0;
    }
    
  • 相关阅读:
    人生苦短之Python的urllib urllib2 requests
    近期测试BUG总结
    人生苦短之Python列表拷贝
    测试发展前景,测试人员的发展方向,测试趋势
    人生苦短之Python函数的健壮性
    Python视频教程
    人生苦短之Python文件的IO操作
    人生苦短之Python枚举类型enum
    人生苦短之Python类的一二三
    人生苦短之Python装饰器
  • 原文地址:https://www.cnblogs.com/LMSH7/p/9579463.html
Copyright © 2011-2022 走看看