物流运输题解
题目大意
从A到B有些路径,每次过边需要成本,且某些天某个点不能被经过,求n天之内,A到B不间断的最小成本。
基本思路
最短路+dp
首先求每天最小成本肯定是要最短路的(dijkstra/spfa,数据不大的floyd也应该可以)
然而换路这个东西是需要成本的,所以需要dp?[本来是想暴力的,然而会gg]
如何dp
首先可知 在第i天时,有变换路径与不变换路径两种选择
如果原来的路径此时不能走了就只好变换路径,就需要k的成本
然而 若在第i天最短路为路径 α \alpha α,第i+1天最短路径变为 β \beta β,第i+2天最短路径变成了 γ \gamma γ,逐天换路的话就需要2*k的成本,但若直接从 α \alpha α换成 γ \gamma γ的话就只需要k的花费
我们可以考虑这样做,求出从第i天到第j天都可以走的最短路成本乘上(j-i+1),加上第i-1天及以前的总成本,再加上换路径的花费k
O ( n 2 ∗ m ) O(n^{2}*m) O(n2∗m) 复杂度能过 ?
代码实现
本人懒 不想写链表 23333333
#include <bits/stdc++.h>
using namespace std;
int n,m,k,e;
int mp[21][21];
int d;
int a[21][110];
int dp[110];
int now[21];
int spfa(){
queue<int> q;
int dis[21];
int vis[21];
memset(dis,0x7f7f7f7f,sizeof dis);
memset(vis,false,sizeof vis);
dis[1]=0;
q.push(1);
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=0;
for(int i=1;i<=m;i++){
if(now[i]) continue;
if(mp[u][i]>0&&dis[i]>dis[u]+mp[u][i]){
dis[i]=dis[u]+mp[u][i];
if(vis[i]==0){
q.push(i);
vis[i]=1;
}
}
}
}
return dis[m];
}
int main(){
ios::sync_with_stdio(false);
cin.tie(false); //关同步优化系列 然而noip不能关
cin>>n>>m>>k>>e;
for(register int i=1;i<=m;i++){ //register 寄存器优化(虽然优化效果甚微)
for(register int j=1;j<=m;j++){ //然而noip暴力优化还有很有用的
mp[i][j]=0x7f7f7f7f; //noip评测机为core i7
} //每秒计算次数大于1e8(远大于洛~谷等网站的1e7)
} //暴力友的福利 233333333
for(register int i=1;i<=e;i++){
int f,t,l;
cin>>f>>t>>l;
mp[f][t]=l;
mp[t][f]=l;
}
cin>>d;
for(register int i=1;i<=d;i++){
int aa,b,p;
cin>>p>>aa>>b;
for(register int j=aa;j<=b;j++){
a[p][j]=1;
}
}
memset(dp,0x7f7f7f7f,sizeof dp);
dp[0]=-k;
for(register int i=1;i<=n;i++){
memset(now,0,sizeof now);
for(register int l=1;l<=m;l++)now[l]=0;
for(register int j=i;j>=1;j--){
for(int l=1;l<=m;l++)now[l]|=a[l][j];
int ll=spfa();
if(ll==0x7f7f7f7f)continue;
dp[i]=min(dp[i],dp[j-1]+ll*(i-j+1)+k);
}
}
cout<<dp[n];
return 0;
}