• bzoj1003物流运输——DP


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1003

    DP好题;

    直接找一个时间段的最短路,并用它来预处理出每个时间段的最小花费;

    f[i]代表一条路走到时间的花费,所以转移要加上K。

    枚举所有路线的TLE代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,m,K,e,head[25],ct,D,d[105],rt[405],pr[405],f[105][405],cnt,ans;
    bool vis[25];
    struct N{
        int to,next,w;
        N(int t=0,int n=0,int w=0):to(t),next(n),w(w) {}
    }edge[805];
    void dfs(int x,int r,int p)
    {
        if(x==m)
        {
            rt[++cnt]=(r|(1<<(m-1)));
            pr[cnt]=p;
            return;
        }
        vis[x]=1;
        for(int i=head[x];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(vis[v])continue;
            dfs(v,(r|(1<<(v-1))),p+edge[i].w);
        }
        vis[x]=0;
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&K,&e);
        for(int i=1,x,y,z;i<=e;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            edge[++ct]=N(y,head[x],z);head[x]=ct;
            edge[++ct]=N(x,head[y],z);head[y]=ct;
        }
        scanf("%d",&D);
        for(int i=1,p,a,b;i<=D;i++)
        {
            scanf("%d%d%d",&p,&a,&b);
            for(int j=a;j<=b;j++)d[j]|=(1<<(p-1));//第j天不能通过的码头
        }
        dfs(1,1,0);
        memset(f,0x3f,sizeof f);
        for(int j=1;j<=cnt;j++)f[0][j]=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=cnt;j++)
            {
                if(rt[j]&d[i])continue;
                for(int k=1;k<=cnt;k++)
                    f[i][j]=min(f[i][j],f[i-1][k]+(j==k?pr[j]:K+pr[j]));
            }
        ans=0x3f;
        for(int j=1;j<=cnt;j++)ans=min(ans,f[n][j]);
        printf("%d",ans);
        return 0;
    }

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    queue<int>q;
    int const inf=0x3f3f3f3f;
    int n,m,K,e,head[25],ct,mr[105][105],D,zt[25],dis[25],f[105];
    bool vis[25],d[25][105];
    struct N{
        int to,next,w;
        N(int t=0,int n=0,int w=0):to(t),next(n),w(w) {}
    }edge[805];
    void spfa()
    {
        memset(vis,0,sizeof vis);
        memset(dis,0x3f,sizeof dis);
        while(q.size())q.pop();
        dis[1]=0;q.push(1);vis[1]=1;
        while(q.size())
        {
            int x=q.front();q.pop();vis[x]=0;
            for(int i=head[x];i;i=edge[i].next)
            {
                int v=edge[i].to;
                if(dis[v]>dis[x]+edge[i].w&&!zt[v])
                {
                    dis[v]=dis[x]+edge[i].w;
                    if(!vis[v])vis[v]=1,q.push(v);
                }
            }
        }
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&K,&e);
        for(int i=1,x,y,z;i<=e;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            edge[++ct]=N(y,head[x],z);head[x]=ct;
            edge[++ct]=N(x,head[y],z);head[y]=ct;
        }
        scanf("%d",&D);
        for(int i=1,p,a,b;i<=D;i++)
        {
            scanf("%d%d%d",&p,&a,&b);
            for(int j=a;j<=b;j++)d[p][j]=1;
        }
        for(int i=1;i<=n;i++)
        {
            memset(zt,0,sizeof zt);
            for(int j=i;j<=n;j++)
            {
                for(int k=1;k<=m;k++)zt[k]|=d[k][j];
                spfa();
                mr[i][j]=dis[m];//在下面乘 小心爆int 
            }
        }
        for (int i=1;i<=n;i++)
            for (int j=i;j<=n;j++)
                if (mr[i][j]<inf)mr[i][j]*=(j-i+1);
        for(int i=1;i<=n;i++)f[i]=mr[1][i];
        for(int i=2;i<=n;i++)
        {
            for(int j=1;j<i;j++)
                f[i]=min(f[i],f[j]+mr[j+1][i]+K);
        }
        printf("%d",f[n]);
        return 0;
    } 
  • 相关阅读:
    【转】我该 不该学习VULKAN
    游戏开发内功秘籍记录
    VS 配置外部DLL的引用路径【可执行文件的环境路径】
    OpenGL3.x,4.x中使用FreeImage显示图片的BUG-黑色,或颜色分量顺序错乱
    C++风格与C风格文件读写效率测试-vs2015,vs2017
    【转】矩阵的几何解释
    android 线程间通信
    android 网络
    安卓 碎片 如何实现类似 活动 栈的 进栈 出栈
    安卓 内容提供者 观察者 解析器
  • 原文地址:https://www.cnblogs.com/Zinn/p/9131969.html
Copyright © 2020-2023  润新知