有n个瓶子,每个瓶子有a[i]的水,每个瓶子容量为b[i],每移动一个单位水小号1秒,问在使用最少个瓶子的前提下,移动水至少需要多少秒
省赛选拔前没做背包专题,后来做了背包专题,现在看这题还是毫无头绪。。。
状态实在太难想了,还是只会参考别人的
参考博客:背包dp
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int mx = 105;
const int inf = 0x3f3f3f3f;
int dp[mx][mx*mx];
struct node {
int a, b;
bool operator < (const node q) {
return b > q.b;
}
}bt[mx];
int main() {
int n, tot = 0, remaining = 0;
scanf("%d",&n);
for (int i = 1; i <= n; i++) {
scanf("%d",&bt[i].a);
remaining += bt[i].a;
}
for (int i = 1; i <= n; i++) {
scanf("%d",&bt[i].b);
tot += bt[i].b;
}
sort(bt+1, bt+1+n);
int tmp = 0, cnt = 0;
for (int i = 1; i <= n; i++) {
tmp += bt[i].b;
if (tmp >= remaining) {
cnt = i;
break;
}
}
memset(dp, -1, sizeof(dp));
dp[0][0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = tot; j >= bt[i].b; j--) {
for (int k = i; k > 0; k--) {
if (dp[k-1][j-bt[i].b] != -1) {
dp[k][j] = max(dp[k][j], dp[k-1][j-bt[i].b] + bt[i].a);
}
}
}
}
int ans = inf;
for (int i = tot; i >= remaining; i--) {
ans = min(ans, remaining - dp[cnt][i]);
}
printf("%d %d\n", cnt, ans);
return 0;
}