题目分析:
做这道题非常尴尬的是在我看了样例之后我才知道我最开始把题目读错了。
先来说说这道题的解题思路。由于并不知道什么时候修改航线,所以我们用动态规划来解决。
D
P
[
I
]
DP[I]
DP[I]表示前
I
I
I天的最小花费,于是我们得到如下的状态转移方程,其中
C
o
s
t
[
I
]
[
J
]
Cost[I][J]
Cost[I][J]表示第
I
I
I天到第
J
J
J天固定航线后的最小花费:
J
<
I
:
D
P
[
I
]
=
m
i
n
(
D
P
[
I
]
,
D
P
[
J
]
+
C
o
s
t
(
J
+
1
,
I
)
+
K
)
J<I:DP[I]=min(DP[I],DP[J]+Cost(J+1,I)+K)
J<I:DP[I]=min(DP[I],DP[J]+Cost(J+1,I)+K)
那么现在问题变成了如何求出
C
o
s
t
(
I
,
J
)
Cost(I,J)
Cost(I,J),我们在上面已经说了
C
o
s
t
(
I
,
J
)
Cost(I,J)
Cost(I,J)表示的是第
I
I
I天后到第
J
J
J天固定航线之后的最小花费,所以我们在跑此时的最短路的时候,根据输入的统计标出当前哪些码头是不可以用的进行判断就可以了。
参考代码:
#include <queue>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define DB double
#define SG string
#define LL long long
#define Fp(A,B,C,D) for(A=B;A<=C;A+=D)
#define Fm(A,B,C,D) for(A=B;A>=C;A-=D)
#define Clear(A) memset(A,0,sizeof(A))
using namespace std;
const LL Mod=1e9+7;
const LL Max=1e4+5;
const LL Inf=1e18;
struct Node{
LL Num,Dis;
bool operator < (const Node &A) const{
return A.Dis<Dis;
}
};
//Flag[I]表示码头I当前是否可以使用
//Busy[I][J]表示码头I在第J天是否可以使用
//Cost[I][J]表示第I天到第J天的最小花费
LL N,M,K,E,D,DP[105],Dis[Max],Vis[Max];
LL Flag[Max],Busy[Max][105],Cost[105][105];
LL Cnt,To[Max<<1],Edge[Max<<1],Next[Max<<1],Head[Max];
inline LL Read(){
LL X=0;char CH=getchar();bool F=0;
while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
return F?-X:X;
}
inline void Write(LL X){
if(X<0)X=-X,putchar('-');
if(X>9)Write(X/10);
putchar(X%10+48);
}
void Insert(LL X,LL Y,LL Z){
To[++Cnt]=Y;Edge[Cnt]=Z;Next[Cnt]=Head[X];Head[X]=Cnt;
}
LL Dijkstra_Heap(){
LL I,J;
priority_queue<Node>Q;
Fp(I,1,M,1){
Vis[I]=0;
Dis[I]=Inf;
}Dis[1]=0;Node Tmp;Tmp.Num=1;Q.push(Tmp);
while(Q.size()){
LL X=Q.top().Num;Q.pop();
if(Vis[X]==false){
Vis[X]=true;
for(I=Head[X];I;I=Next[I]){
LL Y=To[I],Z=Edge[I];
if(!Vis[Y]&&Dis[Y]>Dis[X]+Z&&!Flag[Y]){
Dis[Y]=Dis[X]+Z;
Tmp.Num=Y;
Tmp.Dis=Dis[Y];
Q.push(Tmp);
}
}
}
}
return Dis[M];
}
int main(){
LL I,J,L,H;
N=Read(),M=Read(),K=Read(),E=Read();
Fp(I,1,E,1){
LL X=Read(),Y=Read(),Z=Read();
Insert(X,Y,Z);Insert(Y,X,Z);
}D=Read();
Fp(I,1,D,1){
LL X=Read(),Y=Read(),Z=Read();
Fp(J,Y,Z,1){
Busy[X][J]=1;
}
}
Fp(I,1,N,1){
Fp(J,I,N,1){
Clear(Flag);
Fp(L,1,M,1){//统计当前状态下哪些码头不能使用
Fp(H,I,J,1){
if(Busy[L][H]==1){
Flag[L]=1;
}
}
}
Cost[I][J]=Dijkstra_Heap();
if(Cost[I][J]!=Inf){//这里格外注意
Cost[I][J]*=(J-(I-1));
}
}
}
Fp(I,1,N,1){//DP过程
DP[I]=Cost[1][I];
Fp(J,1,I-1,1){
DP[I]=min(DP[I],DP[J]+Cost[J+1][I]+K);
}
}Write(DP[N]);
return 0;
}