bzoj1003: [ZJOI2006]物流运输(DP+spfa)
1003: [ZJOI2006]物流运输
题目:传送门
题解:
可以用spfa处理出第i天到第j都走这条路的花费,记录为cost
f[i]表示前i天的最小花费:f[i]=min(f[i],f[j-1]+cost*(i-j+1)+k);
水一发代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #define qread(x) x=read() 7 using namespace std; 8 inline int read() 9 { 10 int f=1,x=0;char ch; 11 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return f*x; 14 } 15 int n,m,k,e,D; 16 struct edge 17 { 18 int x,y,d,next; 19 }a[110000];int len,last[510]; 20 void ins(int x,int y,int d) 21 { 22 len++;a[len].x=x;a[len].y=y;a[len].d=d; 23 a[len].next=last[x];last[x]=len; 24 } 25 int flag[510][510],f[510],d[510],list[510]; 26 int spfa(int st,int ed) 27 { 28 for(int i=1;i<=m;i++)d[i]=999999; 29 int head=1,tail=2;list[1]=1;d[1]=0; 30 while(head!=tail) 31 { 32 int x=list[head]; 33 for(int k=last[x];k;k=a[k].next) 34 { 35 int y=a[k].y; 36 if((flag[y][ed]-flag[y][st-1]==0) && (d[y]>d[x]+a[k].d)) 37 { 38 d[y]=d[x]+a[k].d; 39 list[tail++]=y; 40 if(tail==m+1)tail=1; 41 } 42 } 43 head++;if(head==m+1)head=1; 44 } 45 return d[m]; 46 } 47 int main() 48 { 49 qread(n);qread(m);qread(k);qread(e); 50 len=0;memset(last,0,sizeof(last)); 51 for(int i=1;i<=e;i++) 52 { 53 int x,y,d; 54 qread(x);qread(y);qread(d); 55 ins(x,y,d);ins(y,x,d); 56 } 57 scanf("%d",&D); 58 memset(flag,0,sizeof(flag)); 59 for(int i=1;i<=D;i++) 60 { 61 int p,x,y; 62 qread(p);qread(x);qread(y); 63 for(int j=x;j<=y;j++)flag[p][j]=1; 64 } 65 for(int i=1;i<=m;i++) 66 for(int j=1;j<=n;j++) 67 flag[i][j]+=flag[i][j-1]; 68 f[0]=0; 69 for(int i=1;i<=n;i++) 70 { 71 f[i]=999999999; 72 for(int j=1;j<=i;j++) 73 { 74 int cost=spfa(j,i); 75 f[i]=min(f[i],f[j-1]+cost*(i-j+1)+k); 76 } 77 } 78 printf("%d\n",f[n]-k); 79 return 0; 80 }