[BZOJ1003](ZJOI 2006) 物流运输trans
【题目描述】
物流公司要把一批货物从码头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*改变运输路线的次数。
【样例输入】
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
【样例输出】
32
【提示】
前三天走1-4-5,后两天走1-3-5,这样总成本为(2+2)*3+(3+2)*2+10=32
【分析】
用最短路作为权值的区间覆盖问题。可以用spfa预处理出每个区间中“整体可行”的路线中的最短路,然后用动态规划求解。
这样看来,预处理阶段需要对$O(n^2)$个区间进行计算,对于每个区间还要扫描出这个区间哪些节点“可以访问”, 时间可能会有些不够用。怎么办呢?
事实上,这种思路还有很大的优化空间。首先,节点数最多只有20,我们可以用一个32位整数存储当前区间可以访问的节点集合,通过位运算很容易就可以求出这些集合。接着,我们可以优化一下进行spfa的顺序:从小到大枚举区间左端点,再从大到小枚举右端点。这样,在每轮第二层循环中,由于区间规模在缩小,“可以访问的节点”集合规模是单调递增的,于是我们可以仅在第一层循环开始时更新dis数组,然后在第二层循环中判断可访问节点数是否有增加,若有,就将这些节点的邻接点加入队列再进行spfa,否则就直接将上次spfa的dis值当做这一区间的权值。
采用了这种预处理方法后,我的代码在bzoj上运行时间为24ms(大概是因为STL拖慢了速度?反正我知道低于20ms的代码都是2012年以前提交的……)
预处理完成后,剩下的就是一个$O(n)$状态、$O(n)$转移的简单DP了,这里不再赘述。
2 Problem: 1003
3 User: Asm.Def
4 Language: C++
5 Result: Accepted
6 Time:24 ms
7 Memory:1376 kb
8 ****************************************************************/
9
10 #include <iostream>
11 #include <cctype>
12 #include <cstdio>
13 #include <vector>
14 #include <algorithm>
15 #include <cmath>
16 #include <queue>
17 using namespace std;
18 inline void getd(int &x){
19 char c = getchar();
20 bool minus = ;
21 while(!isdigit(c) && c != '-')c = getchar();
22 if(c == '-')minus = , c = getchar();
23 x = c - '';
24 while(isdigit(c = getchar()))x = x * + c - '';
25 if(minus)x = -x;
26 }
27 /*======================================================*/
28 const int maxn = , maxm = , INF = 0x3f3f3f3f;
29
30 struct event{int T, num; } E[];
31 inline bool operator < (const event &a, const event &b){
32 return a.T < b.T;
33 }
34
35 int n, m, K, Ecnt = ;
36 int inval[maxn][maxn] = {}, cost[maxn][maxn], dp[maxn];
37
38 struct edge{
39 int to, w;
40 edge(int t, int c):to(t), w(c){}
41 };
42 vector<edge> adj[maxm];
43
44 queue<int> Q;
45 bool inQ[maxm] = {};
46 int dis[maxm] = {};
47 inline void setinf(){
48 dis[] = ;
49 for(int i = ;i <= m;++i)
50 dis[i] = INF;
51 }
52
53 inline void pushQ(int x){
54 vector<edge>::iterator it;
55 for(int i=, j=;i <= m;++i, j <<= )
56 if(x & j){
57 if(!inQ[i])Q.push(i), inQ[i] = ;
58 for(it = adj[i].begin();it != adj[i].end();++it)
59 if(!inQ[it->to])Q.push(it->to), inQ[it->to] = ;
60 }
61 }
62
63 inline int spfa(int l, int r){
64 vector<edge>::iterator it;
65 int t;
66 while(!Q.empty()){
67 t = Q.front(); Q.pop(); inQ[t] = ;
68 for(it = adj[t].begin();it != adj[t].end();++it)
69 if((!(inval[l][r] & ( << it->to))) && dis[it->to] > dis[t] + it->w){
70 dis[it->to] = dis[t] + it->w;
71 if(!inQ[it->to])
72 Q.push(it->to), inQ[it->to] = ;
73 }
74 }
75 return dis[m];
76 }
77
78 inline void init(){
79 int i, j, e, k, d;
80 getd(n), getd(m), getd(K), getd(e);
81 while(e--){
82 getd(i), getd(j), getd(k);
83 adj[i].push_back(edge(j, k));
84 adj[j].push_back(edge(i, k));
85 }
86 getd(d);
87 while(d--){
88 getd(k), getd(i), getd(j);
89 E[Ecnt].T = i, E[Ecnt].num = k; ++Ecnt;
90 E[Ecnt].T = j+, E[Ecnt].num = k; ++Ecnt;
91 }
92 sort(E, E + Ecnt);
93 for(j = , i = ;i <= n;++i){
94 inval[i][i] = inval[i-][i-];
95 while(j < Ecnt && E[j].T == i){
96 inval[i][i] ^= ( << E[j].num);
97 ++j;
98 }
99 }
for(i = ;i < n;++i)
for(j = i+;j <= n;++j)
inval[i][j] = inval[i][j-] | inval[j][j];
for(i = ;i <= n;++i){
setinf();
Q.push(), inQ[] = ;
cost[i][n] = spfa(i, n);
for(j = n-;j >= i;--j){
if(inval[i][j] == inval[i][j+]){
cost[i][j] = cost[i][j+];
continue;
}
pushQ(inval[i][j] ^ inval[i][j+]);
if(!inQ[])Q.push(), inQ[] = ;
cost[i][j] = spfa(i, j);
}
}
}
inline void work(){
int i, j, c;
for(i = ;i <= n;++i)
dp[i] = cost[][i] == INF ? INF : cost[][i] * i;
for(i = ;i <= n;++i) for(j = ;j < i;++j){
if(cost[j+][i] == INF)continue;
c = dp[j] + cost[j+][i] * (i - j) + K;
if(c < dp[i])
dp[i] = c;
}
printf("%d\n", dp[n]);
}
int main(){
#if defined DEBUG
freopen("test", "r", stdin);
#else
//freopen("bzoj_1002.in", "r", stdin);
//freopen("bzoj_1002.out", "w", stdout);
#endif
init();
work();
#if defined DEBUG
cout << endl << (double)clock()/CLOCKS_PER_SEC << endl;
#endif
return ;
}
spfa预处理+DP
[BZOJ1003](ZJOI 2006) 物流运输trans的更多相关文章
- ZJOI 2006 物流运输 bzoj1003
题目描述 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪. ...
- [ZJOI 2006]物流运输
Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格 ...
- BZOJ-1003 物流运输trans SPFA+DP
傻逼错误耗我1h,没给全范围坑我1A.... 1003: [ZJOI2006]物流运输trans Time Limit: 10 Sec Memory Limit: 162 MB Submit: 529 ...
- bzoj1003[ZJOI2006]物流运输trans
1003: [ZJOI2006]物流运输trans Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常 ...
- 【BZOJ】【1003】【ZJOI2006】物流运输trans
最短路/DP 这题数据规模并不大!!这是重点……… 所以直接暴力DP就好了:f[i]表示前 i 天的最小花费,则有$f[i]=min\{f[j]+cost[j+1][i]+k\} (0\leq j \ ...
- BZOJP1003 [ZJOI2006]物流运输trans
BZOJP1003 [ZJOI2006]物流运输trans 1003: [ZJOI2006]物流运输trans Time Limit: 10 Sec Memory Limit: 162 MB Sub ...
- BZOJ 1003 [ZJOI2006]物流运输trans
1003: [ZJOI2006]物流运输trans Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4242 Solved: 1765[Submit] ...
- BZOJ 1003: [ZJOI2006]物流运输trans(最短路+dp)
1A,爽! cost[i][j]表示从第i天到第j天不改路线所需的最小花费,这个可以用最短路预处理出.然后dp(i)=cost[j][i]+dp(j-1)+c. c为该路线的花费. --------- ...
- BZOJ 1003 物流运输trans dijstra+dp
1003: [ZJOI2006]物流运输trans Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3896 Solved: 1608[Submit] ...
随机推荐
- Port-knocking 简单教程
0. "port knocking" 如字面意思,类似'敲门',只是这里敲的是'端口',而且需要按照顺序'敲'端口.如果敲击规则匹配,则可以让防火墙实时更改策略.从而达到开关防火墙 ...
- css position的值
值 描述 absolute 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位. 元素的位置通过 "left", "top", " ...
- 【EverydaySport】健身笔记——动态牵拉
动态牵拉,包含了动态和牵拉两个概念.动态牵拉要求牵拉的过程要伴随着走路,即行进中牵拉,动态牵拉不仅可以使得肌肉得到延展,还可以激活肌肉协同工作,发展协调性.灵活性.进行动态牵拉时每个动作要进行5~10 ...
- Linux汇编教程03:大小比较操作
我们在上一讲中,简单了解了汇编程序大概的样子.接下来我们来了解一下,汇编程序的大小比较操作.所以我们以编写寻找一堆数中的最大值作为学习的载体. 在编写程序之前,先要分析我们的目的,在得出解决方案. 目 ...
- STL之顺序容器 deque 动态数组
deque是一个动态数组,deque与vector非常类似,vector是一个单向开口的连续线性空间,deque则是双向开口的连续线性空间.两者唯一的区别是deque可以在数组的开头和末尾插入和删除数 ...
- 详解java中的TreeSet集合
TreeSet是实现Set接口的实现类.所以它存储的值是唯一的,同时也可以对存储的值进行排序,排序用的是二叉树原理.所以要理解这个类,必须先简单理解一下什么是二叉树. 二叉树原理简述 假如有这么一个集 ...
- 15:django 缓存架构
动态网站的一个基本权衡就是他们是动态的,每次一个用户请求一个页面,web服务器进行各种各样的计算-从数据库查询到模板渲染到业务逻辑-从而生成站点访问者看到的页面.从处理开销的角度来看,相比标准的从文件 ...
- Binary Tree Postorder Traversal——重要的基本的算法
Given a binary tree, return the postorder traversal of its nodes' values. For example: Given binary ...
- 玩转RaspberryPi
step1:烧制树莓派内存卡 可以用[Linux系统烧制]http://www.williamsang.com/archives/1764.html 如果用windows烧制的话,就用Win32 Di ...
- 云平台学习--GitLab
今天和师父还有孙老师一起,两位大神给我讲了下全世界最先进的云平台架构(Tigzx). 废话不多说,直接说代码的GitLab 第一步: 访问路径:http://git.dlanqi.com:30503, ...