ioi 2005--河流 [左儿子右兄弟]

有一棵树(结点数≤100),在根有一个伐木场,每个结点都有若干木头,每条边都有个距离,所有的木头都要往上运,运过一条边的代价为木头数量乘以边的长度。现在可以在某些结点新建k(≤100)个伐木场,建立伐木场后,木头就不一定要运到根了,可以直接运到新的伐木场。问在合理建设伐木场下,最小的代价是多少。

这很容易想到树形的动态规划,设f(i, j)为这以i为根的子树新建j个伐木场的最小代价。可是如何转移呢?

若i这里新建一个伐木场,则把j - 1个伐木场分配给它的儿子;那假如不新建呢?第i个结点的木头运到哪里去呢?我们可能会这样想:要是知道它的木头能运到哪个结点就好了。数据范围比较小,那就大胆地去尝试,多记一个状态k:距离它最近的有伐木场的祖先(父亲)的编号。这样子记状态,又要注意到子树,又要留意祖先(父亲),可谓是”前瞻后顾“了。

用f(i, j, k)三维的状态表示。假如在i新建一个,那么就是f(son, j', i),其中要做一次背包。若不新建f(son, j' - 1, k) + i到k的距离 * i的木头数。

这样做背包的确比较麻烦,可以用左儿子右兄弟表示法,那么:枚举分配给儿子p个,若新建:f(leftson, p, i) + f(rightson, j - p - 1, k);不新建:f(leftson, p, k) + f(rightson, j - p, k) + i到k的距离 * i的木头数。

这题的时间复杂度似乎与1s擦肩而过,但实际上是没有那么多状态的。还能给我们一些经验:树形DP也是要留意上面的点的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值