CSU 1776/BZOJ 4254 Aerial Tramway(树形dp+topsort)
来源:互联网 发布:淘宝怎么开启返利管理 编辑:程序博客网 时间:2024/06/03 21:06
1776: Aerial Tramway
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 59 Solved: 28
Description
An aerial tramway, cable car, ropeway or aerial tram is a type of aerial lift which uses one or two stationary ropes for support while a third moving rope provides propulsion. With this form of lift, the grip of an aerial tramway cabin is fixed onto the propulsion rope and cannot be decoupled from it during operations. -- Wikipedia
You own a park located on a mountain, which can be described as a sequence of n points (xi, yi) from left to right, where xi,yi>0, xi<xi+1, yi!=yi+1 (that means there will not be horizontal segments in the mountain skyline), illustrated below(the numbers are the corresponding x-coordinate):
Since the mountain is very sloppy, some aerial tramways across the park would be very helpful. In the figure above, people can go from p4 to p9 directly, by taking a tram. Otherwise he must follow a rather zigzag path: p4-p5-p6-p7-p8-p9.
Your job is to design an aerial tramway system. There should be exactly m trams, each following a horizontal segment in the air, between two points pi and pj. "Horizontal" means yi=yj, “in the air" means all the points in between are strictly below, i.e. yk<yi for every i<k<j. For example, no tram can travel between p2 and p9, because p4 is not strictly below p2-p9. However, you can have two trams, one from p2 to p4, and one p4 to p9. There is another important restriction: no point can be strictly below k or more tramways, because it’ll be dangerous. For example, if k=3, we cannot build these 3 tramways simultaneously: p1-p14, p4-p9, p6-p8, because p7 would be dangerous.
You want to make this system as useful as possible, so you would like to maximize the total length of all tramways. For example, if m=3, k=3, the best design for the figure above is p1-p14, p2-p4 and p4-p9, the total length is 20. If m=3, k=2, you have to replace p1-p14 with p11-p13, the total length becomes 9.
Input
There will be at most 200 test cases. Each case begins with three integers n, m and k(1<=n,m<=200, 2<=k<=10), the number of points, the number of trams in your design and the dangerous parameter introduced earlier. The next line contains n pairs of positive integers xi and yi.(1<=xi,yi<=105).
Output
For each test case, print the case number and the maximal sum. If it is impossible to have exactly m tramways, print -1.
Sample Input
14 3 3 1 8 2 6 3 4 4 6 5 3 6 4 7 1 8 4 9 6 10 4 11 6 12 5 13 6 14 8 14 3 2 1 8 2 6 3 4 4 6 5 3 6 47 1 8 4 9 6 10 4 11 6 12 5 13 6 14 8
Sample Output
Case 1: 20 Case 2: 9
Hint
Source
湖南省第十一届大学生计算机程序设计竞赛 给你n个点,然后每个点有横纵坐标,如果两个点高度相同那么可以建立缆车连接线,但是前提是两点连线之间的点高度必须严格低于他们的高度。给你建立m条缆车路线的任务,问你最多能够使得缆车线路总长度为多少。但是要注意,一定是严格建立m条路线,不能多也不能少,如果建不了那么多则输出-1。最后还有一个限制,任何一个点它上面能够有的缆车路线条数严格小于K。
首先这题很容易往dp方面去想,但是说实话想到树形dp还是不简单的。我们把每一个可以建立的缆车路线想象为一个背包,价值为它的长度,就变成了让你取m个物品,使得总价值最大的一个01背包问题。但是由于有一个K的限制,所以必须用上树形dp。
用上树形dp,我们就可以加一维表示到当前点的缆车最大深度。我们把路线的相互包含关系求出来,然后用topsort建立一棵树(设置一个虚拟总根,价值为0),在这棵树上进行dp。我们考虑dp[x][i][j]表示在以x为根的子树中取i条路线,然后最大层叠深度小于等于j的最大长度,那么有三个转移方程:dp[x][i][j]=max(dp[x][i][j],dp[x][i-k][j]+dp[y][k][j]),其中y为x的儿子,这条意思是先不考虑x节点,然后在x的所有儿子中做01背包;做完了这个之后再有dp[x][i+1][j+1]=max(dp[x][i+1][j+1],dp[x][i][j]+w[x]),表示再把当前点也考虑进去;注意到,我定义dp数组的时候,第三维是最大层叠深度小于等于j,注意这个深度是可以小于j的,所以说我们最后还要处理这个,把每一个深度都的值更新为小于等于他的最大值,有dp[x][i][j]=max(dp[x][i][j],dp[x][i][j-1])。
然后,在转移的过程中,要注意由于此题要求取的缆车路线严格等于m,所以我们在初始的时候就要把所有的值赋值为-1,然后在转移过程中,所有的转移一定不能从值为-1的点转移过来。然后初始化的时候是把dp[x][0][i]赋值为0,这个好理解。最后是复杂度,枚举节点是n,枚举取的路线数量是m,深度是K,然后还有枚举儿子,看起来复杂度好像可以到四次方,但是按照树形dp常用的优化方法,每次做背包的时候个数只枚举到当前已经dfs到的数量,可以把复杂度降下来,最后是O(KNM)。
然后具体的还要处理好线段的包含关系以及top sort。具体见代码:
#include<iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<cstring>#include<vector>#include<queue>#define LL long long#define N 210using namespace std;int w[N],size[N],dp[N][N][11];int n,m,K,sz,x[N],y[N],d[N];vector<int> g[N],gra[N];struct seg{int b,e,h;};vector<seg> segment;bool inclusive(int x,int y)//判断两个路线是否是包含关系{ if (segment[x].b>segment[y].b) return 0; if (segment[x].e<segment[y].b) return 0; if (segment[x].h<=segment[y].h) return 0; return 1;}void topsort()//top sort建树{ queue<int> q; for(int i=1;i<=sz;i++) if (!d[i]) { q.push(i); g[0].push_back(i);//0为虚拟的总根 } while(!q.empty()) { int x=q.front(); q.pop(); for(int i=0;i<gra[x].size();i++) { int y=gra[x][i]; if (--d[y]==0) { q.push(y); g[x].push_back(y);//建边 } } }}void dfs(int x){ size[x]=1; for(int i=0;i<=K;i++) dp[x][0][i]=0; for(int i=0;i<g[x].size();i++) { int y=g[x][i]; dfs(y); size[x]+=size[y]; for(int j=min(m,size[x]);j>=0;j--)//每次只枚举到当前size for(int k=0;k<=K;k++) for(int t=0;t<=size[y]&&t<=j;t++)//儿子也只枚举到当前size if (dp[x][j-t][k]>=0&&dp[y][t][k]>=0)//所有转移都不能从-1来 dp[x][j][k]=max(dp[x][j][k],dp[y][t][k]+dp[x][j-t][k]); } for(int i=min(m,size[x])-1;i>=0;i--) for(int j=0;j<K;j++) if (dp[x][i][j]>=0)//把当前点x也考虑进去 dp[x][i+1][j+1]=max(dp[x][i+1][j+1],dp[x][i][j]+w[x]); for(int i=1;i<=K;i++) for(int j=0;j<=size[x]&&j<=m;j++)//处理第三维的小于等于 dp[x][j][i]=max(dp[x][j][i],dp[x][j][i-1]);}void init(){ segment.clear(); memset(d,0,sizeof(d)); memset(g,0,sizeof(g)); memset(gra,0,sizeof(gra)); memset(dp,-1,sizeof(dp)); memset(size,0,sizeof(size));}int main(){ int T_T=0; while(~scanf("%d%d%d",&n,&m,&K)) { init(); K--; for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) { if (y[j]>y[i]) break; if (y[i]==y[j]) { segment.push_back(seg{x[i],x[j],y[i]}); w[segment.size()]=x[j]-x[i]; break; } } sz=segment.size(); for(int i=0;i<sz;i++) for(int j=i+1;j<sz;j++) if (inclusive(i,j)) { d[j+1]++; gra[i+1].push_back(j+1); } topsort(); dfs(0); if (sz<m) printf("Case %d: -1\n",++T_T);//注意一定要特判路线数与m的关系,因为我虚拟了一个总根,所以当 else printf("Case %d: %d\n",++T_T,dp[0][m][K]);//sz比m小1的时候,dp会自动把总根算进去,然后输出一个正数而不是-1 } return 0;}
阅读全文
0 0
- CSU 1776/BZOJ 4254 Aerial Tramway(树形dp+topsort)
- UVA 12929 - Aerial Tramway(dp)
- 2015湖南省赛A题 BZOJ4254 Aerial Tramway 树形dp
- bzoj 4254 树形dp
- bzoj 1040(树形DP)
- bzoj 2060(树形DP)
- bzoj 1907(树形dp)
- bzoj 1060(树形dp)
- bzoj 1131(树形dp)
- bzoj 1369(树形dp)
- bzoj 1304(树形dp)
- bzoj 4726(树形dp)
- bzoj 1596(树形dp)
- 【树DP】UVA12929Aerial Tramway
- CSU 1681 Adjoin(树形dp && 树的直径)
- BZOJ-3227 红黑树(tree) 树形DP
- bzoj 1131: [POI2008]Sta(树形DP)
- bzoj 2196 Computer(树形DP)
- 剑指offer 面试题3:数组中重复的数字
- itchat 把个人的微信号,打造成机器人
- 【位运算】hdu-6186 CS Course
- mongodb的安装
- 进程与线程的一个简单解释
- CSU 1776/BZOJ 4254 Aerial Tramway(树形dp+topsort)
- 虚拟币交易平台在交易中开发哈希现金(HashCash)机制更安全
- python 3.x 错误 ‘generator’ object has no attribute ‘next’
- matplotlib学习笔记
- Jupyter Notebook 的快捷键
- linux查看设置系统时区
- hdfs 上传文件(写数据)流程
- 【物联网安全】应用层与感知终端之间的交互流程
- 最基础的代码设计模式-健壮可靠宽容