bzoj1003/luogu1772 物流运输 (dijkstra+dp)

先求出某一段时间[i,j]一直用同一个路径的最短路,乘上天数,记作cost[i,j]

那就可以设f[i]是前i天的最小代价,f[i]=f[j]+cost[j+1,i]+K

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define ll long long
 4 using namespace std;
 5 const int maxn=110,maxm=25;
 6 
 7 ll rd(){
 8     ll x=0;char c=getchar();int neg=1;
 9     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
10     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
11     return x*neg;
12 }
13 
14 struct Edge{
15     int a,b,l,ne;
16 }eg[maxm*maxm*2];
17 int N,M,K,E,D,egh[maxm],ect;
18 int di[maxm][maxn],dis[maxm],mi[maxm],cost[maxn][maxn];
19 int f[maxn];
20 bool can[maxm][maxn],used[maxm],flag[maxm];
21 
22 inline void adeg(int a,int b,int l){
23     eg[++ect].a=a;eg[ect].b=b;eg[ect].l=l;eg[ect].ne=egh[a];egh[a]=ect;
24 }
25 
26 inline int dijkstra(){
27     priority_queue<pa,vector<pa>,greater<pa> > q;while(!q.empty()) q.pop();
28     memset(dis,127,sizeof(dis));memset(flag,0,sizeof(flag));
29     dis[1]=0;q.push(make_pair(0,1));
30     while(!q.empty()){
31         int p=q.top().second;q.pop();if(flag[p]||!used[p]) continue;
32         if(p==M) break;
33         for(int i=egh[p];i!=-1;i=eg[i].ne){
34             int b=eg[i].b;
35             if(dis[b]>dis[p]+eg[i].l){
36                 dis[b]=dis[p]+eg[i].l;
37                 q.push(make_pair(dis[b],b));
38             }
39         }flag[p]=1;
40     }return dis[M];
41 }
42 
43 inline void pre(){
44     for(int i=1;i<=N;i++){
45         memset(mi,127,sizeof(mi));
46         for(int j=i;j<=N;j++){memset(used,0,sizeof(used));
47             used[1]=used[M]=1;
48             for(int k=2;k<M;k++){
49                 mi[k]=min(mi[k],(int)can[k][j]);
50                 if(mi[k]) used[k]=1;
51             }int re=dijkstra();
52             cost[i][j]=(re>=0x3f3f3f3f)?-1:re*(j-i+1);
53             //printf("%d %d %d\n",i,j,cost[i][j]);
54         }
55     }
56 }
57 
58 int main(){
59     int i,j,k;
60     N=rd(),M=rd(),K=rd(),E=rd();
61     memset(egh,-1,sizeof(egh));
62     for(i=1;i<=E;i++){
63         int a=rd(),b=rd(),c=rd();
64         adeg(a,b,c);adeg(b,a,c);
65     }D=rd();
66     for(i=1;i<=D;i++){
67         int a=rd(),b=rd(),c=rd();
68         di[a][b]=1;di[a][c+1]=-1;
69     }for(i=1;i<=M;i++){
70         for(j=1,k=0;j<=N;j++){
71             k+=di[i][j];can[i][j]=k?0:1;
72         }
73     }pre();memset(f,127,sizeof(f));f[0]=-K;
74     for(i=1;i<=N;i++){
75         for(j=0;j<i;j++){
76             if(cost[j+1][i]==-1) continue;
77             f[i]=min(f[j]+cost[j+1][i]+K,f[i]);
78         }//printf("%d %d\n",i,f[i]);
79     }printf("%d\n",f[N]);
80     return 0;
81 }

 

转载于:https://www.cnblogs.com/Ressed/p/9634191.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值