[BZOJ4182]Shopping

该博客探讨了BZOJ4182题目,分析了如何在树形结构中寻找最优购物策略。通过点分治方法,将问题转化为求解连通块内的最优贡献。博主提出使用树形依赖的多重背包解决每个商店的物品选择,并通过二进制优化处理购物限制,以获得最大收益。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

  点这里看题目。
   BZOJ 上这还是权限题。

分析

  不难发现,最后我们走过的点一定组成了树上的一个连通块。
  如何枚举树上一个连通块?我们可以想到用点分治。由于每一次我们进行分治之后会进行子树继续分治,这就相当于将原图变成了几个连通块。我们只需要对于每次分治,将分治中心设定为 “ 必选 ” ,然后用某种方法计算这个连通块的所有连通子块的最优贡献即可。
  不难发现每个商店的物品可以拿出来做多重背包。因此我们发现可以用树形依赖的多重背包计算贡献。设状态:
   f ( u , j ) f(u,j) f(u,j) u u u的子树中,花 j j j的代价可以获得的最大收益。
  发现存在连通块每个点上都必须买东西的限制,因此我们必须在每个点上,先强制买一个东西之后,再进行多重背包的计算。这相当于总共可用的钱变少了。之后继续搜索,将子树上的答案合并上来。
  由于本题对时间的限制不强,因此可以写多重背包二进制优化。妄图掩盖单调队列写挂的事实。

代码

#include <cstdio>

const int INF = 0x3f3f3f3f;
const int MAXN = 505, MAXM = 4005, MAXD = 105;

template<typename _T>
void read( _T &x )
{
   
	x = 0;char s = getchar();int f = 1;
	while( s > '9' || s < '0' ){
   if( s == '-' ) f = -1; s = getchar();}
	while( s >= '0' && s <= '9' ){
   x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar();}
	x *= f;
}

template<typename _T>
void write( _T x )
{
   
	if( x < 0 ){
    putchar( '-' ); x = ( ~ x ) + 1; }
	if( 9 < x ){
    write( x / 10 ); }
	putchar( x % 10 +
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值