AT_abc410_e
博客
请点击这里享受更好的阅读效果!
题目大意
高桥有两种属性:体力(共
思路
题目明确了我们要按顺序处理,这也大大节省了时间复杂度(无需枚举上一步所在位置)。我们令
我个人认为最好不要把第一位压掉,不然很有可能会造成第
我们考虑如何转移:
- 不使用魔力(即这一维的值为
0 ):\min\lbrace f_{i-1,j+a_i,0},f_{i-1,j+a_i,1}\rbrace ,因为上一步体力至少剩余j+a_i 。 - 使用魔力(即这一维的值为
1 ):\min\lbrace f_{i-1,j,0},f_{i-1,j,1}\rbrace+b_i ,因为上一步体力剩余j 即可,需要额外消耗b_i 魔力。
那么如何求答案呢?显然,我们是要寻找满足最小魔力值不超过魔力上限的最大的
代码
// https://atcoder.jp/contests/abc410/submissions/66760787
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int n, h, m;
int a[3010];
int b[3010];
int f[3010][3010][2];
int main()
{
cin >> n >> h >> m;
for (int i = 1; i <= n; i++)
cin >> a[i] >> b[i];
memset(f, 0x3f, sizeof(f));
for (int i = 0; i <= h; i++)
f[0][i][0] = f[0][i][1] = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 0; j + a[i] <= h; j++)
{
f[i][j][0] = f[i - 1][j + a[i]][0];
f[i][j][0] = min(f[i][j][0], f[i - 1][j + a[i]][1]);
}
for (int j = 0; j <= h; j++)
{
f[i][j][1] = f[i - 1][j][0];
f[i][j][1] = min(f[i][j][1], f[i - 1][j][1]);
f[i][j][1] += b[i];
}
}
for (int i = n; i >= 0; i--)
{
int v = 1e9;
for (int j = 0; j <= h; j++)
v = min(v, min(f[i][j][0], f[i][j][1]));
if (v <= m)
{
cout << i << endl;
return 0;
}
}
return 0;
}