题目大意:
一批货物要从码头
A
A
A运到码头
B
B
B需要
n
n
n天。
希望能够制定一个
n
n
n天的运输计划。
码头总数为
m
m
m,编号为
1
1
1~
m
m
m,码头
A
A
A编号为
1
1
1,码头
B
B
B编号为
m
m
m,每次修改运输路线所需成本为
K
K
K,有
e
e
e条航线,每条航线给出其所连接的两个码头
x
x
x和航线长度,单位长度的运输费用为
1
1
1,航线是双向的。
再给出
d
d
d对限制
(
P
,
a
,
b
)
(P,a,b)
(P,a,b),表示编号为
P
P
P的码头在
[
a
,
b
]
[a,b]
[a,b]无法装卸货物。
同一个码头有可能在多个时间段内不可用。
保证任何时间都存在至少一条从码头
A
A
A到码头
B
B
B的运输路线。
问最小的成本花费总和。
1
<
=
n
<
=
100
,
1
<
=
m
<
=
20
1<=n<=100,1<=m<=20
1<=n<=100,1<=m<=20
1
<
P
<
m
,
1
<
=
a
<
=
b
<
=
n
1 < P < m,1< = a < = b < = n
1<P<m,1<=a<=b<=n
航
线
长
度
>
0
航线长度>0
航线长度>0
分析:
令
c
o
s
t
i
,
j
cost_{i,j}
costi,j表示在
[
i
,
j
]
[i,j]
[i,j]天内使用同一种运输路线的最小花费,
然后可以用
s
p
f
a
spfa
spfa+前缀和判定限制 预处理出来
然后设
d
p
i
dp_i
dpi表示前
i
i
i天的运输计划的最小成本花费总和。
可以推出
初值:
d
p
i
=
c
o
s
t
1
,
i
dp_i=cost_{1,i}
dpi=cost1,i
转移:
d
p
i
=
m
a
x
(
d
p
i
,
d
p
j
+
c
o
s
t
j
+
1
,
i
+
K
)
dp_i=max(dp_i,dp_j+cost_{j+1,i}+K)
dpi=max(dpi,dpj+costj+1,i+K)
最后
d
p
n
dp_n
dpn就是答案
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <algorithm>
#define inf 0x7fffff
#define N 105
#define M 25
using namespace std;
int mincost[N][N], sum[M][N], w[M][M], dis[M], dp[N], n, m, K, e, d;
bool vis[M];
queue <int> Q;
int spfa(int x, int y)
{
while (Q.size()) Q.pop();
for (int i = 1; i <= m; i++) dis[i] = inf;
Q.push(1);
dis[1] = 0;
vis[1] = 1;
while (!Q.empty())
{
int u = Q.front(); Q.pop();
for (int i = 1; i <= m; i++)
if (sum[i][y] - sum[i][x - 1] == 0 && dis[i] > dis[u] + w[u][i])
{
dis[i] = dis[u] + w[u][i];
if (!vis[i])
Q.push(i), vis[i] = 1;
}
vis[u] = 0;
}
return dis[m];
}
int main()
{
scanf("%d %d %d %d", &n, &m, &K, &e);
for (int i = 1; i <= m; i++)
for (int j = 1; j <= m; j++) w[i][j] = inf;
for (int i = 1; i <= e; i++)
{
int x, y, z; scanf("%d %d %d", &x, &y, &z);
w[x][y] = w[y][x] = z;
}
scanf("%d", &d);
for (int i = 1; i <= d; i++)
{
int z, x, y; scanf("%d %d %d", &z, &x, &y);
for ( x; x <= y; x++) sum[z][x] = 1;
}
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++) sum[i][j] += sum[i][j - 1];
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++) mincost[i][j] = (j - i + 1) * spfa(i, j);
for (int i = 1; i <= n; i++)
{
dp[i] = mincost[1][i];
for (int j = 1; j < i; j++)
dp[i] = min(dp[i], dp[j] + mincost[j + 1][i] + K);
}
printf("%d\n", dp[n]);
return 0;
}