bzoj 1003 dp+spfa

    xiaoxiao2021-03-25  78

    题意:m个码头,每天从1号码头到m号码头,有些码头在某些天是不能经过的,每次修改路线要花cost,求n天最小总成本,总成本=n天经过权值和+修改路线次数*cost

    跑n^2遍spfa预处理出第i天到第j天从1号码头到m号码头的最短距离t[i,j]

    对于第i天,我们有两种选择

    (1)从第一天开始就不改变航线

    (2)从第j天开始改变航线一直保持到第i天

    即f[i]=min{t[1,i]*i,f[j]+cost+t[j+1,i]*(i-j)}

    最终答案f[n]

    var n,m,cost,e,l :longint; x,y,z :longint; i,j :longint; last,que,dis :array[0..30] of longint; vis,ff :array[0..30] of boolean; flag :array[0..30,0..110] of boolean; t :array[0..110,0..110] of longint; f :array[0..110] of int64; pre,other,len :array[0..20010] of longint; function min(a,b:int64):int64; begin if a<b then exit(a) else exit(b); end; procedure connect(x,y,z:longint); begin inc(l); pre[l]:=last[x]; last[x]:=l; other[l]:=y; len[l]:=z; end; function spfa(a,b:longint):longint; var h,tl,cur,q,p,i,j:longint; begin fillchar(vis,sizeof(vis),false); fillchar(dis,sizeof(dis),127); fillchar(ff,sizeof(ff),true); for i:=a to b do for j:=1 to m do if flag[j,i] then ff[j]:=false; h:=0; tl:=1; que[1]:=1; dis[1]:=0; while (h<>tl) do begin h:=h mod 105+1; cur:=que[h]; vis[cur]:=false; q:=last[cur]; while (q<>0) do begin p:=other[q]; if (dis[p]>dis[cur]+len[q]) and ff[p] then begin dis[p]:=dis[cur]+len[q]; if not vis[p] then begin tl:=tl mod 105+1; que[tl]:=p; vis[p]:=true; end; end; q:=pre[q]; end; end; exit(dis[m]); end; begin read(n,m,cost,e); for i:=1 to e do begin read(x,y,z); connect(x,y,z); connect(y,x,z); end; // read(e); for i:=1 to e do begin read(x,y,z); for j:=y to z do flag[x,j]:=true; end; // for i:=1 to n do for j:=1 to n do t[i,j]:=spfa(i,j); // f[1]:=t[1,1]; for i:=2 to n do begin f[i]:=int64(t[1,i])*int64(i); for j:=1 to i-1 do f[i]:=min(f[i],f[j]+int64(cost)+int64(t[j+1,i])*int64(i-j)); end; writeln(f[n]); end. ——by Eirlys

    转载请注明原文地址: https://ju.6miu.com/read-24778.html

    最新回复(0)