金苹果岛 - 代码能力最大化问题

题目描述

代码勇者来到了金苹果岛上,金苹果岛上有两种苹果:随处可见的红苹果与稀有美味的金苹果。

勇者的'初始代码能力为 1',他每吃下一个红苹果,代码能力就会得到一定程度的提升(每个红苹果带来的提升可能是不同的,甚至也可能是负的);他每吃下一个金苹果,代码能力就会直接'翻倍'(每个金苹果的效果都是完全相同的)。

岛上的苹果仙子用 n 个红苹果和 m 个金苹果招待了勇者,勇者必须吃光所有苹果。勇者必须按照仙子'规定的顺序'吃红苹果,但是他可以'自由安排'什么时候吃金苹果(可以在吃'任意'一个红苹果之前或之后吃'若干'个金苹果)。

求勇者在离开金苹果岛的时候的代码能力的最大值。

输入格式

第一行输入两个正整数 n(n≤10^5)和 m( m≤10)。

第二行输入 n 个整数 a_i(|a_i|≤10)。

输出格式

输出一个整数,表示勇者在离开金苹果岛的时候的代码能力的最大值。

样例 #1

样例输入 #1

6 2
1 -2 3 1 -6 5

样例输出 #1

15

样例 #2

样例输入 #2

8 3
5 -3 -8 2 4 -11 9 1

样例输出 #2

42

提示

样例1解释

勇者吃掉红苹果 1,-2,3,1,代码能力变为 4;

勇者吃掉 2 颗金苹果,代码能力变为 16;

勇者吃掉红苹果 -6,5,代码能力变为 15。

这是勇者的最优方案。

子任务

对于 10% 的数据,a_i≥0;

对于 30% 的数据,m=0;

对于 70% 的数据,m=1;

对于 100% 的数据,n≤10^5,m≤10,|a_i|≤10。

贪心算法代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    
    vector<int> apples(n);
    for (int i = 0; i < n; i++) {
        cin >> apples[i];
    }
    
    sort(apples.begin(), apples.end());
    
    int ans = 0;
    for (int i = 0; i < n; i++) {
        if (apples[i] < 0 && m > 0) {
            m--;
        } else {
            ans += apples[i];
        }
    }
    
    ans *= (1 << m);
    
    cout << ans << endl;
    
    return 0;
}

代码解释

  1. 读取输入: 读取红苹果数量 n,金苹果数量 m 和每个红苹果的代码能力提升值 a_i。
  2. 排序: 对红苹果能力提升值 a_i 进行升序排序。
  3. 贪心策略: 遍历排序后的红苹果能力提升值 a_i。
    • 如果当前红苹果能力提升值为负数且还有金苹果可用 (m > 0),则吃掉一个金苹果 (m--),并将当前红苹果跳过,因为吃金苹果会将代码能力翻倍,比吃负数提升的红苹果更有利。
    • 否则,将当前红苹果的提升值累加到 ans 中,因为吃正数提升的红苹果总是有效的。
  4. 计算最终代码能力: 将 ans 乘以 2 的 m 次方,因为 m 个金苹果会将代码能力翻倍 m 次。
  5. 输出结果: 输出计算出的最终代码能力 ans。

代码改进

代码可以使用一些更高级的语法来改进,例如:

  1. 使用 auto 关键字简化变量声明: 可以使用 auto 关键字自动推断变量类型,简化代码。

  2. 使用 range-based for 循环简化循环: 可以使用 range-based for 循环简化遍历数组或容器的循环。

  3. 使用 lambda 表达式简化排序: 可以使用 lambda 表达式简化排序操作。

改进后的代码:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    
    vector<int> apples(n);
    for (auto &apple : apples) {
        cin >> apple;
    }
    
    sort(apples.begin(), apples.end(), [](int a, int b) { return a < b; });
    
    int ans = 0;
    for (auto apple : apples) {
        if (apple < 0 && m > 0) {
            m--;
        } else {
            ans += apple;
        }
    }
    
    ans *= (1 << m);
    
    cout << ans << endl;
    
    return 0;
}

其他优化

  1. 使用更有效的排序算法: 如果 n 很大,可以考虑使用更有效的排序算法,例如快速排序或归并排序。
  2. 使用位运算优化: 可以使用位运算优化 (1 << m) 的计算,例如使用 ans <<= m; 来替代。

总结

本题可以使用贪心算法来解决。贪心策略是:优先吃负数提升的红苹果,因为吃金苹果可以将代码能力翻倍,可以抵消负数提升的影响。

金苹果岛 - 代码能力最大化问题

原文地址: https://www.cveoy.top/t/topic/fM1B 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录