BZOJ 1003 物流运输 最短路+dp

传送门

题解:枚举每一对天数 跑n*n/2次最短路,每次跑最短路之前都要传递闭包处理出能不能经过这个码头。

    状态转移方程ans[i]=min(ans[i],ans[j]+dp[j+1][i]+k); 第i天的最小成本是由第j天加上j+1天到i天的成本+转移路线的花费

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
#include <cstring>
#include <iomanip>
#include <set>
#include<ctime>
//#include<unordered_map>
//CLOCKS_PER_SEC
#define se second
#define fi first
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define Pii pair<int,int>
#define Pli pair<ll,int>
#define ull unsigned long long
#define pb push_back
#define fio ios::sync_with_stdio(false);cin.tie(0)
const int N=1e3+10;
const ull base=163;
const int INF=0x3f3f3f3f;
using namespace std;
int head[200],to[N],nx[N],val[N];
int tot=1;
void add(int u,int v,int w){
    to[tot]=v;
    nx[tot]=head[u];
    val[tot]=w;
    head[u]=tot++;
}
int dp[200][200];
int a[200][200];
int dis[200];
int can[200];
int vis[200];
int ans[200];
int n,m,k,e;
priority_queue<Pii,vector<Pii>,greater<Pii> >q;
void dij(int s,int t){
    fill(dis,dis+150,INF);
    memset(vis,0,sizeof(vis));
    dis[1]=0;
    q.push({0,1});
    while(!q.empty()){
        Pii p=q.top();q.pop();
        int u=p.se;
        if(vis[u])continue;
        vis[u]=1;
        for(int i=head[u];i;i=nx[i]){
            int v=to[i];
            if(dis[u]+val[i]<dis[v]&&!can[v]){
                dis[v]=dis[u]+val[i];
                q.push({dis[v],v});
            }
        }
    }
   dp[s][t]=dis[m];
}
int main(){
    scanf("%d%d%d%d",&n,&m,&k,&e);
    for(int i=1;i<=e;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w),add(v,u,w);
    }
    int o;scanf("%d",&o);
    for(int i=1;i<=o;i++){
        int u,l,r;scanf("%d%d%d",&u,&l,&r);
        for(int j=l;j<=r;j++){
            a[u][j]=1;
        }
    }
    for(int i=1;i<=n;i++){
        memset(can,0,sizeof(can));
        for(int j=i;j<=n;j++){
            for(int k=1;k<=m;k++)
                for(int l=i;l<=j;l++)
                    can[k]|=a[k][l];
            dij(i,j);
        }
    }
    for (int i=1;i<=n;++i)
        for (int j=i;j<=n;++j)
            if (dp[i][j]<INF) dp[i][j]*=(j-i+1);
    //fill(ans,ans+150,2000);
    memset(ans,0x3f,sizeof(ans));
    for(int i=1;i<=n;i++)ans[i]=dp[1][i];
    for(int i=2;i<=n;i++){
        for(int j=1;j<i;j++){
            ans[i]=min(ans[i],ans[j]+dp[j+1][i]+k);
           // cout<<ans[i]<<endl;
        }
    }
    cout<<ans[n];
    return 0;
}

 

posted @ 2018-05-27 22:13  采蘑菇的小西佬  阅读(177)  评论(0编辑  收藏  举报