https://www.lydsy.com/JudgeOnline/problem.php?id=1003
题意:某东西运输货物运输
n
n
n次,每次都从
1
1
1到
m
m
m。给你一些路线和花费,问
n
n
n天后的最小花费
限制条件是再某些天,某些点不能经过
更改路线有额外花费
k
k
k
题解: 如果
n
n
n天的路线都不变,那么求一次最短路
d
i
s
t
dist
dist乘上
n
n
n就是答案,但是有些点在某些点无法经过,那么就需要更改路线。
设
d
p
[
i
]
dp[i]
dp[i]表示前
i
i
i天的最小花费
d
p
[
i
]
=
m
i
n
(
d
p
[
i
]
,
d
p
[
j
−
1
]
+
(
i
−
j
+
1
)
∗
d
i
s
t
+
k
)
dp[i] = min(dp[i],dp[j-1]+(i-j+1)*dist+k)
dp[i]=min(dp[i],dp[j−1]+(i−j+1)∗dist+k)
意思是对于
j
j
j小于等于
i
i
i的天,如果在第
j
j
j天变更路线,我们假设第
j
j
j天到第
i
i
i天的路线相同,那么前
i
i
i天的花费就是前
j
−
1
j-1
j−1天的最小花费+第
j
j
j天到第
i
i
i天的路线花费+更改路线的花费。 然后乱搞一下
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
const int maxn = 1005;
const int inf = 0x3f3f3f3f;
int head[maxn],tot;
struct node{
int to,nxt,w;
node(){}
node(int a,int c):to(a),w(c){}
bool operator<(const node C)const{
return w > C.w;
}
}E[maxn];
int n,m,K,e;
int dp[105],cant[25],dis[25],vis[25];
int delay[25][105];
void init(){
memset(head,-1,sizeof(head));
memset(delay,0,sizeof(delay));
tot = 0;
}
void addedge(int u,int v,int w){
E[tot].to = v;
E[tot].nxt = head[u];
E[tot].w = w;
head[u] = tot++;
E[tot].to = u;
E[tot].nxt = head[v];
E[tot].w = w;
head[v] = tot++;
}
int dij(int s,int t){
memset(vis,0,sizeof(vis));
for(int i = 1; i <= m; i++)
dis[i] = inf;
dis[s] = 0;
priority_queue<node>q;
while(!q.empty()) q.pop();
if(cant[s]) return 0;
q.push(node(s,0));
while(!q.empty()){
node now = q.top();
q.pop();
int u = now.to;
if(vis[u]) continue;
vis[u] = 1;
for(int i = head[u]; ~i; i = E[i].nxt){
int to = E[i].to;
if(cant[to]){
continue;
}
if(dis[to] > dis[u]+E[i].w){
dis[to] = dis[u]+E[i].w;
q.push(node(to,dis[to]));
}
}
}
return dis[t];
}
int main(){
scanf("%d%d%d%d",&n,&m,&K,&e);
int a,b,c;
init();
for(int i = 1; i <= e; i++){
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
}
int d;
scanf("%d",&d);
while(d--){
scanf("%d%d%d",&a,&b,&c);
for(int i = b; i <= c; i++)
delay[a][i] = -1;
}
memset(dp,63,sizeof(dp));
dp[0] = -K;
for(int i = 1; i <= n; i++){
memset(cant,0,sizeof(cant));
for(int j = i; j >= 1; j--){
for(int k = 1; k <= m; k++) if(delay[k][j] == -1) cant[k] = 1;
int dist = dij(1,m);
if(dist >= inf) break;
dp[i] = min(dp[i],dp[j-1]+(i-j+1)*dist+K);
}
}
printf("%d\n",dp[n]);
}