BZOJ1003 ZJOI2006 物流运输trans 最短路+一般DP

题意:一批货物从码头A运到码头B,需要n天才能运完,有的时候某个码头会无法装卸货物。这时候就必须修改运输路线,让货物能够按时到达目的地。修改路线会带来额外的成本。物流公司希望能够订一个n天的运输计划,使得总成本尽可能地小。

题解:

首先定义cost[i][j]=从第i天到第j天都可以使用的港口所组成的最短路的费用和,初始化出来就好,如果不存在赋值为INF。

定义f[i]为第i天可以使用的最少花费,那么f[i]=min(f[i],f[j-1]+cose[j][i]*(i-j+1)+K),也就是第i天由第j天都使用cost[i][j]这条路径。初始值f[1]=cost[1][1],f[0]=0。

转移的时候注意两点:①、如果cost[i][j]==INF的话不转移(不存在这样的路径)②、如果j==1的话,那么就是从第1天到第i天都在使用同一条路径,这样就不用加K

#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
 
const int MAXN=100+2;
const int MAXM=20+2;
struct NODE{
    int w,v;
    NODE *next;
    NODE(){}
    NODE(int _w,int _v,NODE *_next):w(_w),v(_v),next(_next){};
}*table[MAXM],mem[2*MAXM*MAXM];
int n,m,K,e,d,cost[MAXN][MAXN],cnt,dist[MAXM],f[MAXN];
bool can[MAXN][MAXM];
queue<int> q;
 
void Insert(int a,int b,int c){
    for(NODE *p=table[a];p;p=p->next){<pre name="code" class="cpp">//我也不确定有没用- -,因为可能存在重边,所以取最小边权
        if(p->v==b){
            p->w=min(p->w,c);
            return;
        }
 
    table[a]=&(mem[cnt++]=NODE(c,b,table[a]));
}
 
bool check(int a,int b,int c){//检查c在第a天到第b天能否使用
    for(int i=a;i<=b;i++)
        if(can[i][c]) return 0;
    return 1;
}
 
void SPFA(int a,int b){
    memset(dist,0X7F,sizeof(dist));
    q.push(1),dist[1]=0;
 
    int now;
    while(!q.empty()){
        now=q.front(),q.pop();
 
        for(NODE *p=table[now];p;p=p->next)
            if(check(a,b,p->v) && dist[p->v]>dist[now]+p->w)
                dist[p->v]=dist[now]+p->w,q.push(p->v);
    }
 
    cost[a][b]=dist[m];
}
 
int main(){
    cin >> n >> m >> K >> e;
    for(int i=1,a,b,c;i<=e;i++){
        cin >> a >> b >> c;
        Insert(a,b,c);Insert(b,a,c);
    }
    cin >> d;
    for(int i=1,P,a,b;i<=d;i++){
        cin >> P >> a >> b;
 
        for(int j=a;j<=b;j++) can[j][P]=1;
    }
 
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
            SPFA(i,j);
 
    memset(f,0X7F,sizeof(f));
    f[1]=cost[1][1],f[0]=0;
 
    for(int i=2;i<=n;i++)
        for(int j=1;j<=i;j++)
            if(cost[j][i]<2139062143)//注意cost的取值
                if(j==1) f[i]=min(f[j-1]+cost[j][i]*(i-j+1),f[i]);//注意边界情况
                else f[i]=min(f[j-1]+cost[j][i]*(i-j+1)+K,f[i]);
 
    cout << f[n] << endl;
     
    return 0;
}
View Code

 

posted @ 2017-02-28 01:30  WDZRMPCBIT  阅读(137)  评论(0编辑  收藏  举报