zoukankan      html  css  js  c++  java
  • Luogu P1772 物流运输

    题面

    DP + 图论好题

    思路:首先DP思路显而易见,题目中有的日期需要修改路线,根据线性DP最经典的套路,就是在一个序列上

    即f[i] =  max(f[i],f[k] + value(k,i))

    然后就是需要算价值的部分,我们肯定要处理最短路,用最短路的值来更新答案,题目中支持离线算法,也就是哪些天不能使用的码头是明确知道的,我们DP的是让k to i 这些天都用同一个运输的路线,这时,我们就需要考虑如何让这些天共用一个最短的运输路径,一开始我的思路是判断每天将不能用的点删去之后比较,但是自己怎么也想不出如何保证这些天可以用同一条路径。关键就在于一个思路,这条最短路需要让k to i这所有的天都能用,意味着即使有一天无法用也不行,就是说必须满足所有天的所有条件,不妨就在一张图上将这些天所有无法用的天一起删去,然后跑一边SPFA或者Dij,数据非常小,所以预处理什么的空空间时间完全足够。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    using namespace std;
    const int M=30;
    const int N=M*M;
    const int INF=0X3f3f3f3f;
    
    int m,n,k,e,d,t;
    int head[M],dis[M];
    bool close[N][M],book[M],vis[M];
    long long cost[N][N],f[N];
    
    struct node{
        int to,w,next;
    } edge[N];
    
    void add(int u,int v,int w){
        edge[ ++ d].to = v; edge[d].w = w;
        edge[d].next = head[u]; head[u] = d; 
    }
    
    int spfa(int x,int y){
        memset(dis,INF,sizeof(dis));
        memset(vis,0,sizeof(vis));
        memset(book,0,sizeof(book)); 
        for(int i = 1;i <= n;i ++){
            for(int j = x;j <= y;j ++)
            if(close[i][j]) book[i] = 1; 
        }
        queue<int> q;
        q.push(1); dis[1] = 0; vis[1] = 1;
        while(!q.empty())
        {
            int u = q.front(); q.pop(); vis[u] = 0;
            for(int i = head[u];i;i = edge[i].next){
                int v = edge[i].to;
                if(book[v]) continue;
                if(dis[v] > dis[u] + edge[i].w){
                    dis[v] = dis[u] + edge[i].w;
                    if(!vis[v]){
                        q.push(v); vis[v] = 1; 
                    }
                }
            }
        }
        return dis[m];
    }
    int main()
    {
        scanf("%d %d %d %d",&n,&m,&k,&e);
        for(int i = 1;i <= e;i ++){
            int u,v,w;
            scanf("%d %d %d",&u,&v,&w);
            add(u,v,w);
            add(v,u,w); 
        } 
        scanf("%d",&t);
        for(int i = 1;i <= t;i ++){
            int p,u,v;
            scanf("%d %d %d",&p,&u,&v);
            for(int j = u;j <= v;j ++){
                close[p][j]=1;
            }
        }
    
        for(int i = 1;i <= n;i ++){
            for(int j = 1;j <= n;j ++){
                cost[i][j] = spfa(i, j); 
            }
        }
    
        for(int i = 1;i <= n;i ++){ 
            f[i] = 1ll * cost[1][i] * i;
            for(int j = 1;j <= i;j ++){
            f[i] = min(f[i], f[j] + 1ll * k + 1ll * cost[j+1][i]*(i-j));
            }
        }
        printf("%lld
    ",f[n]);
        return 0;
    }
  • 相关阅读:
    多测师讲解htm_L标题标签001_高级讲师 肖sir
    Shell特殊变量介绍与实践 $0
    shell 变量定义技巧总结
    shell 环境变量的知识小结
    前端 chrome查看html样式基本操作
    shell 命令 env
    date 命令
    shell 命令 set命令
    shell export 命令
    前端 html span标签
  • 原文地址:https://www.cnblogs.com/Shu-Kuang/p/12774477.html
Copyright © 2011-2022 走看看