由题可知a背包容量和b背包容量最大都是400,而且每个化工包裹只有一个,所以只有选与不选
状态就是前i个包裹中a背包容量为j,b背包容量为k时的最少花费,转移就是当j>=a[i].a,k>=a[i].b时dp[i][j][k]=min(dp[i-1][j][k],dp[i-1][j-a[i].a][k-a[i].b]+a[i].c),否则dp[i][j][k]=dp[i-1][j][k],初始状态dp[0][0][0]=0,其他为inf,又因为gcd(Ma,Mb)=1,所以只需要找到a背包容量为i,b背包容量为j时,Ma*j==Mb*i时最小花费即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
struct node {
int a, b, c;
};
int dp[45][405][405];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n, Ma, Mb;
cin >> n >> Ma >> Mb;
vector<node> a(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i].a >> a[i].b >> a[i].c;
}
memset(dp, 63, sizeof(dp));
dp[0][0][0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= 400; j++) {
for (int k = 0; k <= 400; k++) {
if (j < a[i].a || k < a[i].b) {
dp[i][j][k] = dp[i - 1][j][k];
continue;
}
dp[i][j][k] = dp[i - 1][j][k];
dp[i][j][k] = min(dp[i][j][k], dp[i - 1][j - a[i].a][k - a[i].b] + a[i].c);
}
}
}
int ans = 0x3f3f3f3f;
for (int i = 1; i <= 400; i++) {
for (int j = 1; j <= 400; j++) {
if (i * Mb == j * Ma) {
ans = min(ans, dp[n][i][j]);
}
}
}
if (ans == 0x3f3f3f3f) {
cout << "-1\n";
} else {
cout << ans << '\n';
}
return 0;
}