spfa求出在每天可行状态下最短路,用二进制记录最短路通过的码头状态,同时记录最短路的距离,然后同样的方法求出相邻两天都可行的情况下的最短路
然后dp
f[i+1][j]=min(f[i][j]+w[j],f[i][k]+w[k]+K)
#include<iostream>
#include<cstdio>
#include<cstring>
#define INF 0x3f3f3f3f
using namespace std;
int n,m,K,e;
struct edge
{
int to,ne,w;
}b[405];
int k=0,head[35];
struct edge2
{
int fr,to,w;
}a[405];
int cnt=0;
int s[1<<20],w[1<<20];
int dis[35],q[1<<20],tl,top,pre[405];
bool vis[35];
int v[1<<20];
int f[105][1<<15];
inline int read()
{
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
void add(int u,int v,int w)
{
k++;
b[k].to=v;b[k].ne=head[u];b[k].w=w;head[u]=k;
}
/*void turn(int x,int n)
{
int ss[35]={0};
int num=0;
while(x){
ss[++num]=x%2;
x/=2;
}
for(int i=n;i>num;i--) printf("0");
for(int i=num;i>=1;i--) printf("%d",ss[i]);
printf("\n");
}*/
void spfa()
{
memset(dis,0x7f,sizeof(dis));
memset(vis,0,sizeof(vis));
tl=top=0; dis[1]=0;
q[tl++]=1;vis[1]=1;
while(top<=tl){
int z=q[top++]; vis[z]=0;
for(int i=head[z];i!=-1;i=b[i].ne)
if(dis[b[i].to]>dis[z]+b[i].w){
dis[b[i].to]=dis[z]+b[i].w;
pre[b[i].to]=z;
if(!vis[b[i].to]){
q[tl++]=b[i].to;
vis[b[i].to]=1;
}
}
}
}
inline void pr()
{
for(int i=1;i<=n;i++)
{
memset(b,0,sizeof(b));
memset(head,-1,sizeof(head));k=0;
memset(pre,0,sizeof(pre));
for(int j=1;j<=e;j++)
if(!(v[i]&(1<<a[j].fr-1))&&!(v[i]&(1<<a[j].to-1))){
add(a[j].fr,a[j].to,a[j].w);
add(a[j].to,a[j].fr,a[j].w);
}
spfa();
cnt++;
int zt=0,t=m;
while(t){
zt|=(1<<t-1);
t=pre[t];
}
s[cnt]=zt; w[cnt]=dis[m];
}
for(int i=1;i<n;i++){
int ss=(v[i]|v[i+1]);
memset(b,0,sizeof(b));
memset(head,-1,sizeof(head));k=0;
memset(pre,0,sizeof(pre));
for(int j=1;j<=e;j++)
if(!(ss&(1<<a[j].fr-1))&&!(ss&(1<<a[j].to-1))){
add(a[j].fr,a[j].to,a[j].w);
add(a[j].to,a[j].fr,a[j].w);
}
spfa();
if(dis[n]<INF){
cnt++;
int zt=0,t=m;
while(t){
zt|=(1<<t-1);
t=pre[t];
}
s[cnt]=zt; w[cnt]=dis[m];
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
freopen("bzoj_1003.in","r",stdin);
freopen("bzoj_1003.out","w",stdout);
int x,y,z,p;
n=read();m=read();K=read();e=read();
for(int i=1;i<=e;i++){
a[i].fr=read();a[i].to=read();a[i].w=read();
}
p=read();
for(int i=1;i<=p;i++){
x=read();y=read();z=read();
for(int j=y;j<=z;j++) v[j]|=(1<<x-1);
}
memset(f,0x7f,sizeof(f));
pr();
for(int i=1;i<=cnt;i++)
if(!(s[i]&v[1])){
f[1][i]=w[i];
}
for(int i=1;i<n;i++)
for(int j=1;j<=cnt;j++)
if(!(v[i]&s[j]))
for(int k=1;k<=cnt;k++)
if(!(v[i+1]&s[k])){
if(j==k) f[i+1][k]=min(f[i+1][k],f[i][j]+w[k]);
else f[i+1][k]=min(f[i+1][k],f[i][j]+K+w[k]);
}
int ans=INF;
for(int i=1;i<=cnt;i++)
ans=min(ans,f[n][i]);
printf("%d\n",ans);
return 0;
}