观光景点组合得分问题|豆包MarsCode AI刷题

44 阅读3分钟

问题描述如下:

小R正在研究一组观光景点,每个景点都有一个评分,保存在数组 values 中,其中 values[i] 表示第 i 个观光景点的评分。同时,景点之间的距离由它们的下标差 j - i 表示。 一对景点 (i < j) 的观光组合得分为 values[i] + values[j] + i - j,也就是两者评分之和减去它们之间的距离。

小R想知道,在哪种情况下能够获得观光景点组合的最高得分。

通过对题目的解读,我们首先需要分析组合得分公式 values[i] + values[j] + i - j,可以重写为 scores[i] = values[i] + i 和 scores[j] = values[j] - j。目标变为找到最大的组合得分,即在 i < j 的情况下最大化 scores[i] + scores[j]。为此,我们可以采用线性扫描的方法。首先,初始化一个变量 max_score 来记录到目前为止的最大 scores[i],其初始值设为负无穷。在遍历数组的过程中,对于每个 j,我们计算当前得分 values[j] - j,然后检查当前的组合得分是否大于 max_combined_score,该得分等于 max_score + (values[j] - j)。同时,我们在每一步更新 max_score,确保其记录到达当前 j 时所有 i 的最大 scores[i]。最终,我们得到的最大得分即为所求。通过这种方法,我们能够在 O(n) 的时间复杂度内解决问题,避免了 O(n²) 的嵌套遍历。这样的策略确保了高效性和实现简洁性,能够快速找到观光景点组合的最高得分。


using namespace std;

int solution(vector<int> values) {
    if(values.size() == 1) return 0;
    int maxv = 0 , res = 0;

    for(int i = 0 ; i < values.size() ; i ++)
    {
        res = max(res , values[i] - i + maxv);
        maxv = max(maxv , values[i] + i);
    }
    return res; // Placeholder return
}

int main() {
    cout << (solution({8, 3, 5, 5, 6}) == 11) << endl;
    cout << (solution({10, 4, 8, 7}) == 16) << endl;
    cout << (solution({1, 2, 3, 4, 5}) == 8) << endl;
    return 0;
}

我认为这道题的知识点主要有几个方面。首先是对组合得分公式的重新理解和变换,将复杂的表达式通过数学变换简化为更易于处理的形式。这种重组思维在解决优化问题时非常重要,可以帮助迅速梳理出关键变量。其次,我们运用了线性扫描的方法,通过维护一个最大值来避免重复计算,从而实现 O(n) 的时间复杂度,这强调了在处理问题时考虑算法效率的必要性。第三,求解过程中建立临时变量的思想,使得数据的维护和更新变得高效而清晰,这对许多动态规划和贪心算法的问题同样适用。

这道题给了我们对于以后解题的启发,关键在于理解问题的结构和公式背后的逻辑,必要时进行变量的重构和转换。同时,考虑优化算法的时间复杂度和空间复杂度,优先选择高效的解决方案。进行线性遍历时,要善于维护状态变量,通过更新最大值或最小值来逐步构建最终结果。在解题时培养从简单到复杂的思维习惯,先从小规模和简单的问题入手,逐步扩展到规模更大的场景,这样能够帮助建立稳固的知识框架,提高解题能力。