AT_abc219_d [ABC219D] Strange Lunchbox 的题解
洛谷传送门
AT传送门
思路
第一眼看出是一道动态规划,只不过限制状态有两层。
d p i , j , k \mathit{dp}_{i,j,k} dpi,j,k 表示前 i i i 个物品第一个约束条件取 j j j 个第二个约束条件取 k k k 个的最小方案。
然后可以仿照背包问题将 i i i 那一维给删掉,其实删不删空间都够。
注意这里是至少,因此转移方程为 d p i , j = min ( d p i , j , d p max ( 0 , j − a i . x ) , max ( 0 , k − a i . y ) + 1 ) \mathit{dp}_{i,j}=\min(\mathit{dp}_{i,j},\mathit{dp}_{\max(0,j-a_{i}.x),\max(0,k-a_{i}.y)}+1) dpi,j=min(dpi,j,dpmax(0,j−ai.x),max(0,k−ai.y)+1)。
代码
#include <bits/stdc++.h>
#define lowbit(x) x & (-x)
#define endl "\n"
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
namespace fastIO {
inline int read() {
register int x = 0, f = 1;
register char c = getchar();
while (c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
inline void write(int x) {
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
return;
}
}
using namespace fastIO;
int n, ft, sd, sum1 = 0, sum2 = 0, f[355][355];
pair<int, int> a[355];
int main() {
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
n = read(), ft = read(), sd = read();
for(int i = 1; i <= n;i ++) {
a[i].first = read(), a[i].second = read();
sum1 += a[i].first, sum2 += a[i].second;
}
if(sum1 < ft || sum2 < sd) {
puts("-1");
}
else {
memset(f, 0x3f, sizeof(f));
f[0][0] = 0;
for(int i = 1; i <= n; i ++) {
for(int j = 300; j >= 0; j --) {
for(int k = 300; k >= 0;k --) {
f[j][k] = min(f[j][k], f[max(0, j - a[i].first)][max(0, k - a[i].second)] + 1);
}
}
}
int ans = 0x3f3f3f3f;
for(int i = ft; i <=300; i ++) {
for(int j = sd; j <= 300; j ++) {
ans = min(ans, f[i][j]);
}
}
write(ans);
}
return 0;
}