• 【luogu】P1772物流运输(最短路+DP)


      题目链接

      对于本题我们设ext[i][j]计算第i个码头在前j天总共有几天不能用(其实就一前缀和),设dis[i][j]是从第i天到第j天不变运输路线的最短路径,设f[i]是前i天运输货物的最小花费。

      然后n2*O(spfa)处理出整个dis数组。判断一个码头a从第i天到第j天能不能用的方法是ext[a][j]-ext[a][i-1],如果该数等于0,则说明这几天没有一天不能用,则spfa的时候可以扩展到该码头;否则至少有一天不能用,spfa的时候也就不能扩展。

      接着f[i]=min(f[i],f[j]+dis[j+1][i]*(i-j)+k)  其中i-j是天数,j是枚举的从哪天开始换路线。

      最后f[n]即是答案。

      放上代码

      

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<queue>
    #include<cctype>
    #include<algorithm>
    
    inline int read(){
        int num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    using namespace std;
    queue <int>    q;
    bool vis[100200];
    int dst[1500];
    int dis[150][150];
    int n,m,o,e;
    
    int ext[30][150];
    
    struct Edge{
        int next,to,val;
    }edge[1000200];
    int head[12000],num;
    inline void add(int from,int to,int val){
        edge[++num]=(Edge){head[from],to,val};
        head[from]=num;
    }
    
    void Spfa(int s,int t){
        q.push(1);memset(dst,127/3,sizeof(dst));dst[1]=0;
        while(!q.empty()){
            int from=q.front();    q.pop();vis[from]=0;
            for(int i=head[from];i;i=edge[i].next){
                int to=edge[i].to;
                if(ext[to][t]-ext[to][s-1]>0)    continue;
                if(dst[to]>dst[from]+edge[i].val){
                    dst[to]=dst[from]+edge[i].val;
                    if(vis[to])    continue;
                    q.push(to);    vis[to]=1;
                }
            }
        }
        dis[s][t]=dst[m];
    }
    
    long long f[2000];
    
    int main(){
        memset(f,127/3,sizeof(f));memset(dis,127/3,sizeof(dis));
        n=read(),m=read(),o=read(),e=read();
        f[0]=-o;
        for(int i=1;i<=e;++i){
            int from=read(),to=read(),val=read();
            add(from,to,val);
            add(to,from,val);
        }
        int T=read();
        for(int i=1;i<=T;++i){
            int x=read(),a=read(),b=read();
            for(int j=a;j<=b;++j)    ext[x][j]=1;
        }
        for(int i=1;i<=m;++i)
            for(int j=1;j<=n;++j)    ext[i][j]+=ext[i][j-1];
        for(int i=1;i<=n;++i)
            for(int j=i;j<=n;++j)
                Spfa(i,j);
        for(int i=1;i<=n;++i)
            for(int j=0;j<i;++j){
                if(dis[j+1][i]==dis[0][0])    continue;
                f[i]=min(f[i],f[j]+dis[j+1][i]*(i-j)+o);
            }
        printf("%d",f[n]);
        return 0;
    }
  • 相关阅读:
    rm
    Linux下解包/打包,压缩/解压命令
    虚拟机安装---vm12+ubuntukylin16.04
    mysql-5.6.41-winx64安装
    tensorflow学习笔记一------下载安装,配置环境(基于ubuntu16.04 pycharm)
    大一上学期C语言学习心得总结
    常见HTTP状态码
    Java语言基础及java核心
    linux下安装JMeter(小白教程)
    Linux下安装JDK(小白教程)
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/7891281.html
Copyright © 2020-2023  润新知