zoukankan      html  css  js  c++  java
  • 【刷题】BZOJ 4254 Aerial Tramway

    Description

    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):

    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<=10^5).

    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 4
    7 1
    8 4
    9 6
    10 4
    11 6
    12 5
    13 6
    14 8

    Sample Output

    Case 1: 20
    Case 2: 9

    HINT

    2015年湖南省大学生程序设计竞赛

    Solution

    我们把所有可以建的索道当做一个个区间
    会发现这些区间之间要么互不相关,要么互相包含
    于是就可以将这些区间建成一棵树,我们要做的就是在这棵树里选择正好 (m) 个点,使得点权和最大,并且对于每一条深度递增的链,链上选的点必须小于 (k)
    这个树形dp一下就好了,设 (f_{i,j,p}) 代表到树上 (i) 点,其子树中选 (j) 个,深度递增的链中选的最多的链选的个数为 (k)
    转移方程为 (f_{u,j+r,max(p,t)}=max{f_{u,j,p}+f_{v,r,t}})
    用前缀最大值省去最后第三维的枚举
    就可以过了

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=200+10,MAXP=100000+10,MAXK=20+10,inf=0x3f3f3f3f;
    int n,m,k,e,beg[MAXN],nex[MAXN<<1],to[MAXN<<1],cnt,fa[MAXN],val[MAXN],f[MAXN][MAXN][MAXK],g[MAXN][MAXK],size[MAXN],ans;
    struct node{
    	int id,x,y;
    	inline bool operator < (const node &A) const {
    		return x<A.x;
    	};
    };
    node mountain[MAXN];
    std::vector<node> V[MAXP];
    struct interval{
    	int l,r;
    	inline bool operator < (const interval &A) const {
    		return r-l>A.r-A.l;
    	};
    };
    interval line[MAXN];
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    inline void insert(int x,int y)
    {
    	to[++e]=y;
    	nex[e]=beg[x];
    	beg[x]=e;
    }
    inline void dfs(int x)
    {
    	for(register int i=0;i<=m;++i)
    		for(register int j=0;j<k;++j)f[x][i][j]=-inf;
    	f[x][0][0]=0;
    	for(register int i=beg[x];i;i=nex[i])
    		if(to[i]==fa[x])continue;
    		else
    		{
    			dfs(to[i]);
    			static int q1,q2;
    			for(register int j=0;j<=size[x]+size[to[i]];++j)
    				for(register int p=0;p<k;++p)g[j][p]=f[x][j][p];
    			for(register int j=0;j<=size[x];++j)
    				for(register int p=0;p<=min(size[to[i]],m-j);++p)
    				{
    					q1=-inf,q2=-inf;
    					for(register int t=0;t<k;++t)
    					{
    						chkmax(q1,f[x][j][t]),chkmax(q2,f[to[i]][p][t]);
    						chkmax(g[j+p][t],f[x][j][t]+q2);
    						chkmax(g[j+p][t],f[to[i]][p][t]+q1);
    					}
    				}
    			size[x]+=size[to[i]];
    			for(register int j=0;j<=min(m,size[x]);++j)
    				for(register int p=0;p<k;++p)f[x][j][p]=g[j][p];
    		}
    	if(x)
    	{
    		size[x]++;
    		for(register int i=min(size[x],m)-1;i>=0;--i)
    			for(register int j=k-2;j>=0;--j)chkmax(f[x][i+1][j+1],f[x][i][j]+val[x]);
    	}
    }
    int main()
    {
    	static int cases=0;
    	while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    	{
    		for(register int i=1;i<=1e5;++i)V[i].clear();
    		e=0;memset(beg,0,sizeof(beg));cnt=0;ans=-1;
    		memset(size,0,sizeof(size));
    		memset(fa,0,sizeof(fa));
    		for(register int i=1;i<=n;++i)
    		{
    			int x,y;read(x);read(y);
    			mountain[i]=(node){i,x,y};
    		}
    		std::sort(mountain+1,mountain+n+1);
    		for(register int i=1;i<=n;++i)V[mountain[i].y].push_back(mountain[i]);
    		for(register int i=1;i<=1e5;++i)
    			for(register int j=1,lt=V[i].size();j<lt;++j)
    			{
    				int l=V[i][j-1].id+1,r=V[i][j].id-1,nowh=0;
    				for(register int k=l;k<=r;++k)chkmax(nowh,mountain[k].y);
    				if(nowh<i)line[++cnt]=(interval){V[i][j-1].x,V[i][j].x};
    			}
    		std::sort(line+1,line+cnt+1);
    		for(register int i=1;i<=cnt;++i)
    			for(register int j=i-1;j>=1;--j)
    				if(line[j].l<=line[i].l&&line[i].r<=line[j].r)
    				{
    					insert(i,j),insert(j,i);
    					fa[i]=j;break;
    				}
    		for(register int i=1;i<=cnt;++i)
    		{
    			val[i]=line[i].r-line[i].l;
    			if(!fa[i])insert(0,i),insert(i,0);
    		}
    		fa[0]=-1;dfs(0);
    		for(register int i=0;i<k;++i)chkmax(ans,f[0][m][i]);
    		printf("Case %d: %d
    ",++cases,ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    暑假日报-35
    非确定性有穷状态决策自动机练习题Vol.1 题解 & 总结
    loj数列分块入门 1~9
    第12周作业
    第二阶段考试
    UOJ NOI Round 4
    事件
    爬楼梯
    构造函数输出
    比较版本号大小
  • 原文地址:https://www.cnblogs.com/hongyj/p/9562737.html
Copyright © 2011-2022 走看看