BZOJ 1003 dp+最短路

1003: [ZJOI2006]物流运输

题意:m个码头,从码头1到码头m,连续n天都要运送货物。每一天的花费是总路线长度大小,但如果和前一天的路线不一样,要另处加上k元花费。而且有些码头有些天不能用,问这n天的最小费用。

tags:菜鸡一开始真没想到是dp

求n天时最小花费,就要想到以天数为阶段进行规划。dp[i][j]表示第i天到第j天走同一条路线的花费,则f[i]=min( f[i], f[j]+dp[j+1][i]+k )。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define F(i,b,a)  for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 200;
const ll inf=1e18;

int n, m, k, e1, d1, q[10000], head[N], tot;
ll c[N][N], dis[N], f[N];
bool vis[N], use[N], flag[N][N];
struct Edge{int to, next; ll w;}e[N*N];
void Addedge(int u, int v, ll w) { e[++tot].to=v, e[tot].w=w, e[tot].next=head[u], head[u]=tot; };
ll spfa(int x, int y)
{
    mes(use, 0);  mes(vis, 0);
    FF(i,1,m) dis[i]=inf;   dis[1]=0;
    FF(i,x,y) FF(j,1,m) if(flag[j][i]) use[j]=1;
    int t=0, h=0;
    q[++t]=1, dis[1]=0;
    while(h!=t) {
        int u=q[++h]; vis[u]=1;
        for(int i=head[u]; i; i=e[i].next) {
            int v=e[i].to;  ll w=e[i].w;
            if(use[v]==0 && dis[v]>dis[u]+w) {
                dis[v]=dis[u]+w;
                if(vis[v]==0) q[++t]=v, vis[v]=1;
            }
        }
        vis[u]=0;
    }
    return dis[m]*(dis[m]>=inf ? 1 : (y-x+1));
}
void Init()
{
    scanf("%d %d %d %d", &n, &m, &k, &e1);
    int u, v, p, a, b;
    ll w;
    FF(i,1,e1) {
        scanf("%d %d %lld", &u, &v, &w);
        Addedge(u, v, w);  Addedge(v, u, w);
    }
    scanf("%d", &d1);
    FF(i,1,d1) {
        scanf("%d %d %d", &p, &a, &b);
        FF(j,a,b) flag[p][j]=1;
    }
    FF(i,1,n) FF(j,1,i) c[j][i]=spfa(j, i);
}
void DP()
{
    FF(i,1,n) {
        f[i]=c[1][i];
        FF(j,1,i-1) f[i]=min(f[i], f[j]+c[j+1][i]+k);
    }
    printf("%lld
", f[n]);
}
int main()
{
    //freopen("in.txt", "r", stdin);
    Init();
    DP();

    return 0;
}
原文地址:https://www.cnblogs.com/sbfhy/p/6412166.html