📅  最后修改于: 2023-12-03 15:28:28.049000             🧑  作者: Mango
这是一道经典的动态规划问题,可以用类似于背包问题的思路来解决。
给定一个包含 n 个非负整数的数组 nums,要求从 nums 中选取尽可能多的数,并删除其中的一些元素,使得剩下的数的下标可以被 3 整除,最终需要使得被选中的数的总和最大。
在解决该问题时要考虑以下两个因素:
首先,我们可以定义一个数组 dp,其中 dp[i] 表示前 i 个数中元素下标可以被 3 整除的最大和。
对于第一个因素,我们可以先将 nums 数组按从大到小排序,然后从左到右依次遍历,并判断删除当前元素后是否可以使当前下标被 3 整除。如果可以,则将该元素的值加入 dp 数组中,否则 dp[i] 的值与 dp[i-1] 相等。具体实现如下:
sort(nums.begin(), nums.end(), greater<int>());
for (int i = 0; i < n; ++i) {
if (i % 3 == 0) {
dp[i] = nums[i] + dp[i-1];
} else {
dp[i] = dp[i-1];
}
}
对于第二个因素,我们需要注意到当一个数被选中时,它的下一个元素和下下个元素也必须被删除。为了处理这个问题,我们可以采用分组思想,即将下标分为若干个组,每个组包含 3 个元素。如果第一个元素被选中,则需要删除第二个和第三个元素,因此将这三个元素看作一个整体,将它们两两相邻地放在一个组中。同样地,对于每个 i%3==1 的元素也需要将其及其后面的两个元素放在一个组中。最终,我们只需要保证在选取数的同时,必须选择所有在当前组中的元素。
具体实现如下:
int ans = 0;
for (int i = 0; i < n; i += 3) {
ans += dp[i];
}
return ans;
int maxSum(vector<int>& nums) {
int n = nums.size();
vector<int> dp(n);
sort(nums.begin(), nums.end(), greater<int>());
for (int i = 0; i < n; ++i) {
if (i % 3 == 0) {
dp[i] = nums[i] + dp[i-1];
} else {
dp[i] = dp[i-1];
}
}
int ans = 0;
for (int i = 0; i < n; i += 3) {
ans += dp[i];
}
return ans;
}
此题是一道典型的动态规划问题,通过分析问题并考虑两个因素,我们可以得出一个简单且高效的解决方案。