[ZJOI2006]物流运输 瞎跑spfa+瞎dp....
【题目描述】
物流公司要把一批货物从码头A运到码头B。由于货物量比较大,需要n天才能运完。货物运输过程中一般要转停好几个码头。物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪。由于各种因素的存在,有的时候某个码头会无法装卸货物。这时候就必须修改运输路线,让货物能够按时到达目的地。但是修改路线是一件十分麻烦的事情,会带来额外的成本。因此物流公司希望能够订一个n天的运输计划,使得总成本尽可能地小。
【输入格式】
第一行是四个整数n(1<=n<=100)、m(1<=m<=20)、K和e。n表示货物运输所需天数,m表示码头总数,K表示每次修改运输路线所需成本。接下来e行每行是一条航线描述,包括了三个整数,依次表示航线连接的两个码头编号以及航线长度(>0)。其中码头A编号为1,码头B编号为m。单位长度的运输费用为1。航线是双向的。再接下来一行是一个整数d,后面的d行每行是三个整数P( 1 < P < m)、a、b(1 < = a < = b < = n)。表示编号为P的码头从第a天到第b天无法装卸货物(含头尾)。同一个码头有可能在多个时间段内不可用。但任何时间都存在至少一条从码头A到码头B的运输路线。
【输出格式】
包括了一个整数表示最小的总成本。总成本=n天运输路线长度之和+K*改变运输路线的次数。
solution
这个题真的是瞎跑就行
先预处理出cost[i][j] 从i天到j天不换路的最短路费用 、road[i][j] 从第i天到第j天路径 (二进制存储)
f[i]表示前i天的最小费用 g[i]表示前i天最后一次换的路径
f[i]=min(f[j]+cost[j+1][i]+ (g[j]==road[j+1][i]?0:k) ) (0<=j<i)
f[0]=-k
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<queue> 5 #define mem(a,b) memset(a,b,sizeof(a)) 6 using namespace std; 7 struct son 8 { 9 int v,next,w; 10 }; 11 son a1[10006]; 12 int first[10006],e; 13 void addbian(int u,int v,int w) 14 { 15 a1[e].w=w; 16 a1[e].v=v; 17 a1[e].next=first[u]; 18 first[u]=e++; 19 } 20 21 int n,m,k,num; 22 int u,o,p,l; 23 int ji[106][26],flag[26][106][106]; 24 int cost[106][106],lu[106][106]; 25 int f[106],g[106]; 26 27 queue<int> q; 28 int d[26],r[26],vis[26]; 29 void spfa(int o,int p) 30 { 31 mem(vis,0);mem(d,1);mem(r,0); 32 d[1]=0;r[1]|=1;vis[1]=1;q.push(1); 33 while(!q.empty()) 34 { 35 int now=q.front();q.pop();vis[now]=0; 36 for(int i=first[now];i!=-1;i=a1[i].next) 37 { 38 int temp=a1[i].v; 39 if(flag[temp][o][p])continue; 40 if(d[temp]>d[now]+a1[i].w) 41 { 42 d[temp]=d[now]+a1[i].w; 43 r[temp]=r[now]|(1<<(temp-1)); 44 if(!vis[temp]) 45 { 46 q.push(temp); 47 vis[temp]=1; 48 } 49 } 50 } 51 } 52 } 53 54 void SPFA() 55 { 56 for(int i=1;i<=n;++i) 57 for(int j=i;j<=n;++j) 58 { 59 spfa(i,j); 60 cost[i][j]=d[m]*(j-i+1); 61 lu[i][j]=r[m]; 62 } 63 } 64 65 void out11() 66 { 67 printf("\n"); 68 for(int i=1;i<=n;++i) 69 printf("i=%d f[i]=%d\n",i,f[i]); 70 /*for(int i=1;i<=n;++i) 71 { 72 for(int j=1;j<=n;++j) 73 printf("%d ",cost[i][j]); 74 printf("\n"); 75 } 76 printf("\n"); 77 for(int i=1;i<=n;++i) 78 { 79 for(int j=1;j<=n;++j) 80 printf("%d ",lu[i][j]); 81 printf("\n"); 82 }*/ 83 printf("\n"); 84 } 85 86 int main(){ 87 88 //freopen("1.txt","r",stdin); 89 90 //freopen("bzoj_1003.in","r",stdin); 91 //freopen("bzoj_1003.out","w",stdout); 92 93 mem(first,-1); 94 95 scanf("%d%d%d%d",&n,&m,&k,&num); 96 for(int i=1;i<=num;++i) 97 { 98 scanf("%d%d%d",&u,&o,&p); 99 addbian(u,o,p); 100 addbian(o,u,p); 101 } 102 scanf("%d",&l); 103 for(int i=1;i<=l;++i) 104 { 105 scanf("%d%d%d",&u,&o,&p); 106 for(int j=o;j<=p;++j) 107 ji[j][u]=1; 108 } 109 for(int pp=1;pp<=m;++pp) 110 for(int i=1;i<=n;++i) 111 { 112 int temp=0; 113 for(int j=i;j<=n;++j) 114 { 115 if(ji[j][pp]) 116 temp=1; 117 flag[pp][i][j]=temp; 118 } 119 } 120 121 SPFA(); 122 123 //out11(); 124 125 mem(f,1); 126 g[0]=0; 127 f[0]=-k; 128 for(int i=1;i<=n;++i) 129 for(int j=0;j<i;++j) 130 if(f[i]>f[j]+cost[j+1][i]+(g[j]==lu[j+1][i]?0:k)) 131 { 132 f[i]=f[j]+cost[j+1][i]+(g[j]==lu[j+1][i]?0:k); 133 g[i]=lu[j+1][i]; 134 } 135 //out11(); 136 cout<<f[n]; 137 //while(1); 138 return 0; 139 }