题意:
有k个blocks,每个具有高度 h,量 cnt 个,并且拼凑成的块不能超过高度 hmax。
现在问,这些块最高能叠多高。
解析:
完全背包的变形。
首先对所有块按照他们各自的最大高度排序,这样完了以后每次所使用的 hmax,就是当前最大的,相当于完全背包里面背包的容量了;
然后用 dp [ i ] 来表示 当前 高度 i 可不可叠成,用 sum [ i ] 来表示 当前高度 i 使用 当前块的个数。
然后取出最大可以凑成的高度即可。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <climits>
#include <cassert>
#define LL long long
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1
using namespace std;
const int maxn = 40000 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);
struct Block
{
int h, hmax, cnt;
} block[maxn];
bool cmp(Block a, Block b)
{
return a.hmax < b.hmax;
}
bool dp[maxn];
int sum[maxn];
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
int k;
while (~scanf("%d", &k))
{
for (int i = 0; i < k; i++)
{
scanf("%d%d%d", &block[i].h, &block[i].hmax, &block[i].cnt);
}
sort(block, block + k, cmp);
memset(dp, false, sizeof(dp));
dp[0] = true;
int ans = 0;
for (int i = 0; i < k; i++)
{
memset(sum, 0, sizeof(sum));
for (int j = block[i].h; j <= block[i].hmax; j++)
{
if (!dp[j] && dp[j - block[i].h] && sum[j - block[i].h] + 1 <= block[i].cnt)
{
dp[j] = true;
sum[j] = sum[j - block[i].h] + 1;
ans = max(ans, j);
}
}
}
printf("%d\n", ans);
}
return 0;
}