题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3981
题意: 很明显当我们可以继续取物品的时候 我们应该先取小的那一个 这样可以保证得到的价值 最大
dp[i][j] 表示第一组取前i个 第二组取前j个
dp[i][j] = max(dp[i][j-1] + v2 * 剩余空间, dp[i-1][j] + v1 * 剩余空间)
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 2100;
ll dp[N][N];
ll v1, v2, c;
ll n, m, s1[N], s2[N], a1[N], a2[N];;
int main() {
int T;
scanf("%d", &T);
while(T--) {
scanf("%d%d%d", &v1, &v2, &c);
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%d", &a1[i]);
for(int i = 1; i <= m; i++) scanf("%d", &a2[i]);
sort(a1 + 1, a1 + 1 + n);
sort(a2 + 1, a2 + 1 + m);
for(int i = 1; i <= n; i++)
s1[i] = s1[i - 1] + a1[i];
for(int i = 1; i <= m; i++)
s2[i] = s2[i - 1] + a2[i];
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
dp[i][j] = 0;
ll ans = 0;
for(int i = 1; i <= n; i++)
{
if(s1[i] > c) break;
dp[i][0] = v1 * (c - s1[i]) + dp[i - 1][0];
ans = max(ans, dp[i][0]);
}
for(int i = 1; i <= m; i++)
{
if(s2[i] > c) break;
dp[0][i] = v2 * (c - s2[i]) + dp[0][i - 1];
ans = max(ans, dp[0][i]);
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
ll cnt = s1[i] + s2[j];
if(cnt > c) break;
dp[i][j] = max(dp[i - 1][j] + v1 * (c - cnt), dp[i][j - 1] + v2 * (c - cnt));
ans = max(ans, dp[i][j]);
}
printf("%lld\n", ans);
}
return 0;
}