Description
物流公司要把一批货物从码头A运到码头B。由于货物量比较大,需要 n天才能运完。货物运输过程中一般要转停好几个码头。物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪。由于各种因素的存 在,有的时候某个码头会无法装卸货物。这时候就必须修改运输路线,让货物能够按时到达目的地。但是修改路线是一件十分麻烦的事情,会带来额外的成本。因此 物流公司希望能够订一个n天的运输计划,使得总成本尽可能地小。
Input
第一行是四个整数n(1<=n<=100)、m(1& lt;=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的 运输路线。
Output
包括了一个整数表示最小的总成本。总成本=n天运输路线长度之和+K*改变运输路线的次数。
Sample Input
5 5 10 8
1 2 1
1 3 3
1 4 2
2 3 2
2 4 4
3 4 1
3 5 2
4 5 2
4
2 2 3
3 1 1
3 3 3
4 4 5
1 2 1
1 3 3
1 4 2
2 3 2
2 4 4
3 4 1
3 5 2
4 5 2
4
2 2 3
3 1 1
3 3 3
4 4 5
Sample Output
Sample Output
32
32
HINT
前三天走1-4-5,后两天走1-3-5,这样总成本为(2+2)*3+(3+2)*2+10=32
一开始自以为想到很好的一个方法,再想想还是不对。。。。
所以很猥琐的看了题解:
解法:spfa+DP
cost[i][j] 表示从 i 天到 j 天满足条件的源点到汇点的最短路径,用spfa搞定;
f[i] 表示从第一天到第 i 天最小花费;
DP公式:
f[0]=-k;
f[i]=min(f[i],f[j]+cost[j+1][j]*(i-j)+k); (0<=j<i)
另外WA了几次,是因为有重边而且数据溢出 o(╯□╰)o
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<fstream> 6 #define Edgsize 6000000 7 #define Nodesize 2000000 8 #define Maxint 100000000 9 10 using namespace std; 11 //ifstream cin("cin.in"); 12 13 int n,m,S,T; 14 int to[Edgsize],next[Edgsize],weight[Edgsize],head[Nodesize],edgs=0; 15 int dis[Nodesize]; 16 typedef struct { 17 int num,d; 18 }Heap;Heap heap[Nodesize],temp; 19 20 int seat(int x,int y,int z){ 21 if(z==1) return (x-1)*(m-1)+y; 22 else return (n-1)*(m-1)+(x-1)*(m-1)+y; 23 } 24 25 void Addedg(int u,int v,int d){ 26 edgs++;to[edgs]=v;next[edgs]=head[u];weight[edgs]=d;head[u]=edgs; 27 edgs++;to[edgs]=u;next[edgs]=head[v];weight[edgs]=d;head[v]=edgs; 28 } 29 30 int ans=Maxint; 31 void Init(){ 32 //cout<<" sdf";system("pause"); 33 cin>>n>>m; 34 35 S=(n-1)*(m-1)*2+1;T=S+1; 36 memset(head,-1,sizeof(head)); 37 38 int d; 39 40 if(n==1||m==1) 41 { 42 for(int i=1;i<n||i<m;++i) 43 {cin>>d;if(d<ans) ans=d;}return ; 44 } 45 46 for(int i=1;i<=n;++i) 47 for(int j=1;j<m;++j) 48 { 49 cin>>d; 50 if(i==1) Addedg(S,seat(1,j,1),d); 51 else if(i==n) Addedg(seat(i-1,j,2),T,d); 52 else Addedg(seat(i-1,j,2),seat(i,j,1),d); 53 } 54 55 for(int i=1;i<n;++i) 56 for(int j=1;j<=m;++j) 57 { 58 cin>>d; 59 if(j==1) Addedg(seat(i,j,2),T,d); 60 else if(j==m) Addedg(seat(i,j-1,1),S,d); 61 else Addedg(seat(i,j-1,1),seat(i,j,2),d); 62 } 63 64 for(int i=1;i<n;++i) 65 for(int j=1;j<m;++j) 66 { 67 cin>>d; 68 Addedg(seat(i,j,1),seat(i,j,2),d); 69 } 70 71 } 72 73 74 int len=1; 75 void Down(int site){ 76 77 while(1) 78 {//cout<<"down"<<endl; 79 int least=site,left=2*site,right=2*site+1; 80 if(left<=len&&heap[left].d<heap[least].d) least=left; 81 if(right<=len&&heap[right].d<heap[least].d) least=right; 82 83 if(least!=site) 84 { 85 swap(heap[site],heap[least]); 86 site=least; 87 } 88 else break; 89 90 } 91 92 } 93 94 void Up(int site){ 95 int f=site/2; 96 while(f>0&&heap[site].d<heap[f].d) 97 { 98 swap(heap[site],heap[f]); 99 site=f; 100 f/=2; 101 } 102 } 103 104 void Delete_min(int l){ 105 if(l==0) return ; 106 swap(heap[1],heap[l+1]); 107 Down(1); 108 } 109 110 111 void Dijkstra(){ 112 for(int i=1;i<=T;++i) 113 dis[i]=Maxint; 114 heap[1].num=S;heap[1].d=0;dis[S]=0; 115 116 for(int i=1;i<=T&&len>0;++i) 117 { 118 temp=heap[1]; 119 len--; 120 Delete_min(len); //cout<<" sdfg"<<endl; 121 122 for(int j=head[temp.num];j!=-1;j=next[j]) 123 if(dis[to[j]]>dis[temp.num]+weight[j]) 124 { 125 dis[to[j]]=dis[temp.num]+weight[j]; 126 len++;//cout<<len<<" "<<endl; 127 heap[len].num=to[j];heap[len].d=dis[to[j]]; 128 Up(len); 129 } 130 // system("pause"); 131 } 132 cout<<dis[T]<<endl; 133 } 134 135 int main(){ 136 Init();///cout<<n<<" "<<m<<endl; 137 if(ans!=Maxint) {cout<<ans<<endl;return 0;} 138 Dijkstra(); 139 //system("pause"); 140 return 0; 141 142 }