题意:
给两个序列s1,s2,每个序列都有一个系数k1,k2,现在有一个总容量c,要求从这两个序列中取数,使得最后的价值最大。每个数放进背包之后获得的价值为(当前容量-这个数占的容量)*当前序列的系数。
思路:
已知总数n和m较小,易知每个序列放入背包的顺序应该是从小到大的,所以dp[i][j]表示将s1序列的第1...i数和s2序列的第1...j数放入背包时取得的最大价值。s[i][j]表示将s1序列的第1...i数和s2序列的第1...j数放入背包时所占的容量。
则dp[i][j] = max(dp[i-1][j] + (c - s[i][j])*k1 + dp[i][j-1] + (c - s[i][j])*k2);
通过memset初始化会TLE。
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2005;
ll dp[maxn][maxn];
ll s[maxn][maxn];
ll s1[maxn], s2[maxn];
int T, k1, k2, c, n, m;
int main() {
for(scanf("%d", &T); T--;) {
scanf("%d %d %d", &k1, &k2, &c);
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; ++i) {
scanf("%lld", &s1[i]);
}
for(int i = 1; i <= m; ++i) {
scanf("%lld", &s2[i]);
}
sort(s1+1, s1+n+1);
sort(s2+1, s2+m+1);
// memset(dp, 0, sizeof dp);
for(int i = 0; i <= n+1; ++i) {
for(int j = 0; j <= m+1; ++j) {
dp[i][j] = 0;
s[i][j] = 0;
}
}
s[1][1] = c;
for(int i = 1; i <= n+1; ++i) {
if(i != 1) {
s[i][1] = s[i-1][1] - s1[i-1];
if(s[i][1] <= 0) break;
}
for(int j = 2; j <= m+1; ++j) {
s[i][j] = s[i][j-1] - s2[j-1];
if(s[i][j] <= 0) break;
}
s[i][m+1] = s[i][m] - s2[m];
}
ll ans = 0;
for(int i = 1; i <= n+1; ++i) {
for(int j = 1; j <= m+1; ++j) {
if(s[i][j] <= 0) break;
if(i > 1) {
dp[i][j] = max(dp[i][j], dp[i-1][j] + s[i][j]*k1);
}
if(j > 1) {
dp[i][j] = max(dp[i][j], dp[i][j-1] + s[i][j]*k2);
}
ans = max(ans, dp[i][j]);
}
}
printf("%lld\n", ans);
}
return 0;
}
/*
dp[i][j] = max(dp[i-1][j] + s[i][j]*k1, dp[i][j-1] + s[i][j]*k2)
*/
继续加油~