luogu P1772 [ZJOI2006]物流運輸
阿新 • • 發佈:2021-06-24
題面傳送門
我們設\(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]); }