1. 程式人生 > 其它 >luogu P1772 [ZJOI2006]物流運輸

luogu P1772 [ZJOI2006]物流運輸

題面傳送門
我們設\(F_{i,j}\)表示\(i,j\)天內都走同一條路徑的最短路的權值,那麼就是把只要在\([i,j]\)內不能走的都不能走,然後跑spfa即可。
然後開始dp,設\(dp_i\)表示到\(i\)天的最小花費就可以得到\(dp_i=dp_j+F_{i+1,j}\times (i-j)+k\)
直接搞即可。時間複雜度\(O(n^2\times SPFA)\)
code:

#include <vector>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#include<bitset>
#include<set>
#include<map>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 200
#define M 20
#define mod 1000000007
#define eps (1e-7)
#define U unsigned int
#define IT set<ques>::iterator
#define Gc() getchar() 
I void read(int &x){
	char s=getchar();x=0;while(s<'0'||s>'9') s=Gc(); 
	while(s>='0'&&s<='9') x=x*10+s-48,s=Gc();
}
using namespace std;
int n,m,k,W,fl[M+5],x,y,z,D[M+5],F[N+5][N+5],G[M+5][N+5],now;ll dp[N+5];
struct yyy{int to,w,z;}tmp;
struct ljb{
	int head,h[N+5];yyy f[N*N<<1];
	I void add(int x,int y,int z){f[++head]=(yyy){y,z,h[x]};h[x]=head;}
}s;queue<int> Q;
int main(){
	freopen("1.in","r",stdin);
	re int i,j,h;read(n);read(m);read(W);read(k);while(k--) scanf("%d%d%d",&x,&y,&z),s.add(x,y,z),s.add(y,x,z);
	read(k);while(k--) read(x),read(y),read(z),G[x][y]++,G[x][z+1]--;for(i=1;i<=m;i++) for(j=1;j<=n;j++) G[i][j]+=G[i][j-1];
	for(i=1;i<=n;i++){
		for(memset(fl,0,sizeof(fl)),j=i;j<=n;j++){
			for(h=1;h<=m;h++) fl[h]|=G[h][j];memset(D,0x3f,sizeof(D));D[1]=0;Q.push(1);while(!Q.empty()){
				now=Q.front();Q.pop();for(h=s.h[now];h;h=tmp.z) tmp=s.f[h],!fl[tmp.to]&&D[tmp.to]>D[now]+tmp.w&&(Q.push(tmp.to),D[tmp.to]=D[now]+tmp.w);
			}F[i][j]=D[m];
		}
	}
	dp[0]=-W;for(i=1;i<=n;i++){
		for(dp[i]=1e18,j=0;j<i;j++) dp[i]=min(dp[j]+(ll)F[j+1][i]*(i-j)+W,dp[i]);
	}printf("%d\n",dp[n]);
}