• 【BZOJ1003】物流运输(ZJOI2006)-DP+最短路


    测试地址:物流运输
    做法:本题需要用到DP+最短路。
    容易想到,我们可以把这些天分成若干个区间,每个区间使用同一条运输路线,最优的运输路线当然就是不经过任何这几天中禁入的码头的最短路线,然后就是一个裸的区间型DP了,注意特判从一开始就使用同一条路线的情况即可。总的时间复杂度为O(n2m2)
    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define inf 2000000000
    using namespace std;
    int n,m,k,e,d,f[110],dis[25],g[25][25];
    int forbid[110][25]={0},forb[25];
    bool vis[25];
    
    void dijkstra()
    {
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=m;i++) dis[i]=inf;
        dis[1]=0;vis[1]=1;
        for(int i=1;i<=m;i++)
            if (g[1][i]!=-1&&!forb[i]) dis[i]=g[1][i];
        for(int i=1;i<m;i++)
        {
            int v=-1,mn=inf;
            for(int i=1;i<=m;i++)
                if (!vis[i]&&dis[i]<mn) mn=dis[i],v=i;
            if (v==-1) break;
            vis[v]=1;
            for(int i=1;i<=m;i++)
                if (g[v][i]!=-1&&!forb[i]) dis[i]=min(dis[i],dis[v]+g[v][i]);
        }
    }
    
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&k,&e);
        for(int i=1;i<=m;i++)
            for(int j=1;j<=m;j++)
                g[i][j]=-1;
        for(int i=1;i<=e;i++)
        {
            int a,b,d;
            scanf("%d%d%d",&a,&b,&d);
            if (g[a][b]==-1) g[a][b]=g[b][a]=d;
            else g[a][b]=g[b][a]=min(g[a][b],d);
        }
        scanf("%d",&d);
        for(int i=1;i<=d;i++)
        {
            int p,a,b;
            scanf("%d%d%d",&p,&a,&b);
            forbid[a][p]++,forbid[b+1][p]--;
        }
        for(int i=2;i<=n;i++)
            for(int j=1;j<=m;j++)
                forbid[i][j]+=forbid[i-1][j];
    
        f[0]=0;
        for(int i=1;i<=n;i++)
        {
            f[i]=inf;
            for(int j=1;j<=m;j++) forb[j]=0;
            for(int j=i;j>=2;j--)
            {
                for(int l=1;l<=m;l++)
                    forb[l]+=forbid[j][l];
                dijkstra();
                if (dis[m]==inf) break;
                f[i]=min(f[i],f[j-1]+(i-j+1)*dis[m]+k);
            }
            if (dis[m]!=inf)
            {
                for(int j=1;j<=m;j++)
                    forb[j]+=forbid[1][j];
                dijkstra();
                if (dis[m]!=inf) f[i]=min(f[i],i*dis[m]);
            }
        }
    
        printf("%d",f[n]);
    
        return 0;
    }
  • 相关阅读:
    Learn Orleans 04
    Learn Orleans 03
    Learn Orleans 02
    Learn Orleans 01
    Python 导入 Excel 到数据库
    visio 2016/2019 时序图/序列图,修改消息的实线/虚线 箭头问题 返回消息状态
    steeltoe简单使用
    AOP in .NET
    centos 8 docker安装以及兼容性问题处理
    ef core SoftDelete Multi-tenancy 软删除、多租户实现 Global Query Filters
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793550.html
Copyright © 2020-2023  润新知