3180. 执行操作可获得的最大总奖励 I(1849)

给你一个整数数组 rewardValues,长度为 n,代表奖励的值。

最初,你的总奖励 x 为 0,所有下标都是 未标记 的。你可以执行以下操作 任意次

  • 从区间 [0, n - 1] 中选择一个 未标记 的下标 i
  • 如果 rewardValues[i] 大于 你当前的总奖励 x,则将 rewardValues[i] 加到 x 上(即 x = x + rewardValues[i]),并 标记 下标 i

以整数形式返回执行最优操作能够获得的 最大 总奖励。

示例 1:

**输入:**rewardValues = [1,1,3,3]

**输出:**4

解释:

依次标记下标 0 和 2,总奖励为 4,这是可获得的最大值。

示例 2:

**输入:**rewardValues = [1,6,4,3,2]

**输出:**11

解释:

依次标记下标 0、2 和 1。总奖励为 11,这是可获得的最大值。

提示:

  • 1 <= rewardValues.length <= 2000
  • 1 <= rewardValues[i] <= 2000

解答:背包没有限制但有物品添加条件限制,其中每个物品价值为1,求最大价值和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public int maxTotalReward(int[] rewardValues) {
int nums[] = Arrays.stream(rewardValues).toArray();
int n = nums.length;
Arrays.sort(nums);
int MAX = nums[n-1]*2;
// f[i][j]:在考虑前i个value时,是否能取到总奖励j
int f[][] = new int[n+1][MAX], res = 0;
f[0][0] = 1; // 初始化!!
for (int i = 0; i < n; i++) {
int value = nums[i];
for (int j = 0; j < MAX; j++) {
f[i+1][j] = f[i][j];
if (j-value >= 0 && value > j-value) {
f[i+1][j] = Math.max(f[i+1][j], f[i][j-value]);
}
if (f[i+1][j] == 1) res = Math.max(res, j);
}
// System.out.println(Arrays.toString(f[i+1]));
}
return res;
}
}

优化:减少一个维度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public int maxTotalReward(int[] rewardValues) {
int nums[] = Arrays.stream(rewardValues).toArray();
int n = nums.length;
Arrays.sort(nums);
int MAX = nums[n-1]*2;
int f[] = new int[MAX], res = 0;
f[0] = 1; // 初始化!!
for (int i = 0; i < n; i++) {
int value = nums[i];
for (int j = 0; j < MAX; j++) {
if (j-value >= 0 && value > j-value) {
f[j] = Math.max(f[j], f[j-value]);
}
if (f[j] == 1) res = Math.max(res, j);
}
}
return res;
}
}