【BZOJ1003】【ZJOI2006】物流运输trans 最短路预处理+动态规划

链接:

#include <stdio.h>
int main()
{
    puts("转载请注明出处[vmurder]谢谢");
    puts("网址:blog.csdn.net/vmurder/article/details/44569117");
}

题解:

首先我们跑出 fi,j 表示i到j这些天都是相同路线的最小代价。
然后暴力维护 gi 表示前i天最小代价。

fi,j 可以枚举 ij ,暴力处理哪些点不能用,然后跑最短路。
时间复杂度
暴力处理废点 O(n3m)
SPFA 是 O(n2spfa) 大约 O(n2m2)

反正能过。
然后暴力处理废点部分可以缩掉一个 n 降低时间复杂度上限。
就是类似利用单调性质哒。每次枚举i后都单调处理。详见代码。

代码:

p、n、m、y:天数、点数、边数、改路代价。

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 110
#define M 1300
#define inf 0x3f3f3f3f
using namespace std;
struct Eli
{
    int v,len,next;
}e[M];
int head[N],cnt;
inline void add(int u,int v,int len)
{
    e[++cnt].v=v;
    e[cnt].len=len;
    e[cnt].next=head[u];
    head[u]=cnt;
}

bool Dida[N],in[N];
int dist[N];
queue<int>q;
inline void spfa()
{
    memset(dist,0x3f,sizeof dist);
    int i,u,v;
    q.push(1),dist[1]=0;
    while(!q.empty())
    {
        u=q.front(),in[u]=0,q.pop();
        for(i=head[u];i;i=e[i].next)
        {
            v=e[i].v;
            if(Dida[v])continue;
            if(dist[v]>dist[u]+e[i].len)
            {
                dist[v]=dist[u]+e[i].len;
                if(!in[v])q.push(v),in[v]=1;
            }
        }
    }
    return ;
}

int n,m,p,y;
bool dida[N][N];

int f[N][N],g[N];

int main()
{
    freopen("test.in","r",stdin);

    int i,j,k;
    int a,b,c;

    scanf("%d%d%d%d",&p,&n,&y,&m);
    while(m--)
    {
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c),add(b,a,c);
    }
    scanf("%d",&m);
    while(m--)
    {
        scanf("%d%d%d",&a,&b,&c);
        for(i=b;i<=c;i++)dida[a][i]=1;
    }
    for(i=1;i<=p;i++)
    {
        memset(Dida,0,sizeof Dida);
        for(j=i;j<=p;j++)
        {
            for(k=1;k<=n;k++)
                Dida[k]|=dida[k][j];
            spfa();
            f[i][j]=dist[n];
        }
    }
    for(i=1;i<=p;i++)g[i]=(f[1][i]<inf)?(f[1][i]*i):inf;
    for(i=1;i<=p;i++)for(j=0;j<i;j++)if(f[j+1][i]<inf)
        g[i]=min(g[i],g[j]+f[j+1][i]*(i-j)+y);
    printf("%d\n",g[p]);
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值