[AtCoder Educational DP Contest] X - Tower(贪心 + dp)

problem

luogu

你有 n n n 个箱子,编号从 1 到 n,每个箱子有三个属性,以第 i i i 个箱子为例,分别是重量 w i w_i wi,承重能力 s i s_i si,价值 v i v_i vi

你想建一座塔,因此需要将一些箱子堆叠起来,但是每个箱子必须满足下面的条件:

  • 这个箱子上面的所有箱子重量和要小于这个箱子的承重能力。

定义一个塔的价值为它所用的所有箱子的价值和。

最大化这个塔的价值并输出它。

solution

这种前后两个顺序有优劣差别,但不会影响除两个物品外的其余物品,每个物品具有多个属性的题目。

往往需要进行局部最优性的属性排序,然后再做一遍背包即可。

这里考虑相邻的两个物品 i , j i,j i,j

设前面物品的总重量为 W W W,显然这两个的顺序不会影响后面物品的摆放。

假设 i i i 必须放在 j j j 前面才行。

则有 W + w j ≤ s i ∧ s j < W + w i W+w_j\le s_i\wedge s_j<W+w_i W+wjsisj<W+wi,两式相加有 w j + s j < w i + s i w_j+s_j<w_i+s_i wj+sj<wi+si

所以将所有物品按 s + w s+w s+w 排序后做一遍背包即可。

code

#include <bits/stdc++.h>
using namespace std;
#define int long long
int f[1005][20005];
int n;
struct node { int w, s, v; }it[1005];
signed main() {
	scanf( "%lld", &n );
	for( int i = 1;i <= n;i ++ ) 
		scanf( "%lld %lld %lld", &it[i].w, &it[i].s, &it[i].v );
	sort( it + 1, it + n + 1, [](node x, node y ){ return x.w + x.s < y.w + y.s; } );
	for( int i = 1;i <= n;i ++ )
		for( int j = 0;j <= 2e4;j ++ ) {
			if( j <= it[i].s ) 
				f[i + 1][j + it[i].w] = max( f[i + 1][j + it[i].w], f[i][j] + it[i].v );
			f[i + 1][j] = max( f[i + 1][j], f[i][j] );
		}
	int ans = 0;
	for( int i = 0;i <= 2e4;i ++ ) ans = max( ans, f[n + 1][i] );
	printf( "%lld\n", ans );
	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值