洛谷P1772 [ZJOI2006]物流运输 题解

时间:2023-03-08 22:56:43
洛谷P1772 [ZJOI2006]物流运输 题解

题目描述

物流公司要把一批货物从码头A运到码头B。由于货物量比较大,需要n天才能运完。货物运输过程中一般要转停好几个码头。物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪。由于各种因素的存在,有的时候某个码头会无法装卸货物。这时候就必须修改运输路线,让货物能够按时到达目的地。但是修改路线是—件十分麻烦的事情,会带来额外的成本。因此物流公司希望能够订一个n天的运输计划,使得总成本尽可能地小。

输入输出格式

输入格式:

第一行是四个整数n(l≤n≤100)、m(l≤m≤20)、K和e。n表示货物运输所需天数,m表示码头总数,K表示每次修改运输路线所需成本。接下来e行每行是一条航线描述,包括了三个整数,依次表示航线连接的两个码头编号以及航线长度(>0)。其中码头A编号为1,码头B编号为m。单位长度的运输费用为1。航线是双向的。再接下来一行是一个整数d,后面的d行每行是三个整数P(1<P<m),a,b(1≤a≤b≤n)。表示编号为P的码头从第a天到第b天无法装卸货物(含头尾)。同一个码头有可能在多个时间段内不可用。但任何时间都存在至少一条从码头A到码头B的运输路线。

输出格式:

包括了一个整数表示最小的总成本。总成本=n天运输路线长度之和+K*改变运输路线的次数。

输入输出样例

输入样例#1:
  5 5 10 8
1 2 1
1 3 3
1 4 2
2 3 2
2 4 4
3 4 1
3 5 2
4 5 2
4
2 2 3
3 1 1
3 3 3
4 4 5
输出样例#1:
32

说明

【样例输入说明】

洛谷P1772 [ZJOI2006]物流运输 题解

上图依次表示第1至第5天的情况,阴影表示不可用的码头。

【样例输出说明】

前三天走1-4-5,后两天走1-3-5,这样总成本为(2+2)*3+(3+2)*2+10=32。

_NOI导刊2010提高(01)

————————————————我是分割线——————————————

最短路+dp 好题

预处理每天的最短路,再dp选择。

可以用f[i]表示到第i天的时候最小费用,那么f[i]={f[j]+cost[j+1,i]+K}(0<=j<i),其中cost[i,j]表示由第i天到第j天都可以走得通的最短路。

这样求完之后再减去一个多余的K即可。(当然你也可以在预处理时做手脚)

 /*
Problem:
OJ:
User: S.B.S.
Time:
Memory:
Length:
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstdlib>
#include<iomanip>
#include<cassert>
#include<climits>
#include<functional>
#include<bitset>
#include<vector>
#include<list>
#include<map>
#define F(i,j,k) for(int i=j;i<k;i++)
#define M(a,b) memset(a,b,sizeof(a))
#define FF(i,j,k) for(int i=j;i>=k;i--)
#define maxn 1001
#define inf 0x3f3f3f3f
#define maxm 1001
#define mod 998244353
//#define LOCAL
using namespace std;
int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,m;
int k,e,dd;
int mp[maxn][maxn],h[maxn][maxn],a[maxn][maxn];
int d[maxn];
int dp[maxn],q[maxn];
bool vis[maxn];
inline void init()
{
M(mp,);int x,y,z;
F(i,,e){
cin>>x>>y>>z;
if(mp[x][y]==||mp[x][y]>z) mp[x][y]=mp[y][x]=z;
}
M(h,);
cin>>dd;
F(i,,dd){
cin>>x>>y>>z;
for(int j=y;j<=z;j++) h[x][j]=;
}
for(int i=;i<=m;i++)
{
a[i][]=;
for(int j=;j<=n;j++) a[i][j]=a[i][j-]+h[i][j];
}
}
inline int spfa(int u,int v)
{
int hd,tl;
hd=tl=;
M(d,0x3f);M(vis,);
q[tl++]=;d[]=;
while(hd!=tl){
int i=q[hd++];
vis[i]=;
for(int j=;j<=m;j++)
{
if(mp[i][j]&&a[j][v]-a[j][u]==&&d[i]+mp[i][j]<d[j])
{
d[j]=d[i]+mp[i][j];
if(!vis[j]){
vis[j]=;
q[tl++]=j;
}
}
}
}
return d[m];
}
inline void solve()
{
int t;M(dp,0x3f);
dp[]=;
for(int i=;i<=n;i++)F(j,,i)
{
int kk=spfa(j,i);
if(kk!=inf&&(t=dp[j]+kk*(i-j)+k)<dp[i]) dp[i]=t;
}
cout<<dp[n]-k<<endl;
}
int main()
{
std::ios::sync_with_stdio(false);//cout<<setiosflags(ios::fixed)<<setprecision(1)<<y;
#ifdef LOCAL
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
#endif
while(cin>>n>>m>>k>>e){
init();
solve();
}
return ;
}

p1772