ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 UVA12727 The Sightseeing Tour

2021-08-24 12:02:27  阅读:253  来源: 互联网

标签:aaa i1 题解 UVA12727 Tour 32 望远镜 Mx dp


题意

有 \(n\) 个景点,\(m\) 个望远镜,第 \(i\) 个望远镜的视野为 \([A_i,B_i]\) 中的景点,价格为 \(C_i\)。现在有 \(k\) 批游客,第 \(i\) 批游客有 \(Y_i-X_i+1\) 个人,分别愿意支付最多 \(X_i\sim Y_i\) 元钱。对于每个游客,你可以供给他一些可让他挑选的望远镜,他会选择能看到所有景点且不超过他愿意支付的最高钱数的花费最小的方案,求最大总收益。

题解

首先把 \(A,B\) 离散化,这样 \(n\) 就没用了。

其次不可能有两个望远镜的 \(A\) 或 \(B\) 相同,不然去掉视野范围更小的对游客更优。

再定睛一看数据范围,不难想到 dp。

设 \(dp_{i,j,k}\) 表示当前可以看到 \([1,i]\) 且去掉看到 \(i\) 的望远镜后可以看到 \([1,j]\),花费为 \(k\) 的方案是否存在。

我们将所有望远镜按照 \(A\) 从小到大排序,如果 \(A\) 相等再按照 \(B\) 从大到小排序,原因在 dp 之后说明。

枚举望远镜 \(i\) 和去掉 \(i\) 后看到的最右景点 \(i1\),转移 \(dp_{B_i,i1,k+C_i}=\oplus_{j=0}^{\max(A_i-1,1)-1}dp_{i1,j,k}\),其中 \(\oplus\) 表示或运算。

为了使方案合法,即不存在从中去掉一个望远镜仍能看到同样大小视野或不能完全覆盖的情况,\(i1\) 的枚举范围应为 \([A_i-1,B_i-1]\),\(j\) 的枚举范围应为 \([0,\max(A_i-1,1)-1]\)。\(i1\) 很好理解,\(j\) 是因为如果去掉看到 \(i1\) 的望远镜后最右景点为 \(j\) 且 \(j\ge A_i\),那么用 \(j\) 和 \(i\) 两个望远镜就可以覆盖 \(i1\) 的视野,也就是说去掉 \(i1\) 对游客来说是更优的。至于为什么 \(A_i-1\) 要和 \(1\) 取 \(\max\),是因为当 \(A_i\) 是 \(1\) 的时候如果不取 \(\max\) 就无法转移过来,或者理解成从 \(-1\) 转移过来,但是避免数组负数所以取 \(\max\)(也可以整体坐标 \(+1\))。

了解了 dp 过程之后,现在解释一下为什么要这么排序。对于两个望远镜 \(i,j\),如果它们的视野互不包含,那么它们之间是互相影响的,\(A\) 小的会对 \(A\) 大的产生影响,所以 \(A\) 要从小到大排序。至于 \(B\),按理说顺序不要紧,但我们可以发现 dp 中并没有记录已经考虑了几个望远镜,所以说这就相当于背包问题中用了滚动数组,要从后往前考虑,因此 \(B\) 要从大到小排序。

dp 完之后,我们就可以知道哪些价格的方案是可行的,注意到对于一个游客价格最高只可能是 \(300\),把 \(X,Y\) 缩小到这个范围,再预处理一下前缀和即可。

时间复杂度 \(O(\frac{Tm^4c}{\omega})\),其中 \(c\) 是 \(C\) 的最大值 \(10\),\(\omega\) 是 dp 过程 bitset 的优化,为 \(32\) 或 \(64\)。

Code

#include<cstdio>
#include<algorithm>
#include<bitset>
#define LL long long
using namespace std;
int n,m,k,m1,p_t,Mx,la,Test_num;LL ans;
int A[32],B[32],C[32],id[32],pre[302];
bitset<302> u;
bitset<302> dp[184][184];
struct aaa
{
	int val,id;
}p[184];
inline bool cmp(aaa a,aaa b)
{
	return a.val<b.val? 1:0;
}
inline bool cmp1(int a,int b)
{
	return (A[a]==A[b]? (B[a]>B[b]):(A[a]<A[b]));
}
int main()
{
	dp[0][0][0]=1,scanf("%d",&Test_num);
	for(int T=1;T<=Test_num;++T)
	{
		scanf("%d%d%d",&n,&m,&k),p_t=Mx=ans=la=0,u.reset(),m1=(m<<1);
		for(int i=1;i<=m;++i)scanf("%d%d%d",&A[i],&B[i],&C[i]),p[2*i-1]=(aaa){A[i],2*i-1},p[2*i]=(aaa){B[i],2*i},id[i]=i,Mx+=C[i];
		for(int i=1;i<=m;++i)
		{
			if(A[i]>1)p[++m1]=(aaa){A[i]-1,0};
			if(B[i]>1)p[++m1]=(aaa){B[i]-1,0};
			if(A[i]<n)p[++m1]=(aaa){A[i]+1,0};
			if(B[i]<n)p[++m1]=(aaa){B[i]+1,0};
		}
		p[++m1]=(aaa){1,0},p[++m1]=(aaa){n,0},sort(p+1,p+m1+1,cmp);
		for(int i=1;i<=m1;++i)
		{
			if(p[i].val!=p[i-1].val)++p_t;
			if(p[i].id)
			{
				if(p[i].id&1)A[(p[i].id+1)/2]=p_t;
				else B[p[i].id/2]=p_t;
			}
		}
		sort(id+1,id+m+1,cmp1);
		for(int i=1;i<=p_t;++i)
			for(int j=0;j<=p_t;++j)
				dp[i][j].reset();
		for(int i=1;i<=m;++i)
			for(int i1=A[id[i]]-1;i1<B[id[i]];++i1)
				for(int j=0;j<max(A[id[i]]-1,1);++j)
					dp[B[id[i]]][i1]|=(dp[i1][j]<<C[id[i]]);
		for(int i=0;i<=p_t;++i)
			for(int j=1;j<=Mx;++j)
				if(dp[p_t][i][j])
					u[j]=1;
		for(int i=1;i<=Mx;++i)
		{
			if(u[i])la=i;
			pre[i]=pre[i-1]+la;
		}
		for(int i=1,x,y;i<=k;++i)
		{
			scanf("%d%d",&x,&y),--x;
			if(y>Mx)ans+=1LL*(y-Mx)*la,y=Mx;
			if(x>Mx)ans-=1LL*(x-Mx)*la,x=Mx;
			ans+=pre[y]-pre[x];
		}
		printf("Case #%d: %lld\n",T,ans);
	}
	return 0;
}

标签:aaa,i1,题解,UVA12727,Tour,32,望远镜,Mx,dp
来源: https://www.cnblogs.com/18Michael/p/15179698.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有