ZJOI物流运输
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; }