问题描述
小R正在研究一组观光景点,每个景点都有一个评分,保存在数组 values 中,其中 values[i] 表示第 i 个观光景点的评分。同时,景点之间的距离由它们的下标差 j - i 表示。
一对景点 (i < j) 的观光组合得分为 values[i] + values[j] + i - j,也就是两者评分之和减去它们之间的距离。
小R想知道,在哪种情况下能够获得观光景点组合的最高得分。
测试样例
样例1:
输入:
values = [8, 3, 5, 5, 6]
输出:11
样例2:
输入:
values = [10, 4, 8, 7]
输出:16
样例3:
输入:
values = [1, 2, 3, 4, 5]
输出:8
问题理解
我们需要找到一对景点 (i, j),其中 i < j,使得 values[i] + values[j] + i - j 的值最大。这个表达式可以分解为两部分:
values[i] + ivalues[j] - j
数据结构选择
我们可以使用一个变量来记录当前最大的 values[i] + i,然后在遍历数组时,计算 values[j] - j 并与当前最大值相加,更新最大得分。
废话不多说,上代码(完整代码需小伙伴自己组合)
int solution(std::vector<int> values) {
int max_score=0;
int max_i=std::numeric_limits<int>::min();
for(int i=0;i<values.size();i++){
int current_score=max_i+values[i]-i;
max_score=max(current_score,max_score);
max_i=max(max_i,values[i]+i);
}
return max_score;
}
算法步骤
-
初始化一个变量
max_score用于存储最大得分,初始值为负无穷大。 -
初始化一个变量
max_i用于存储当前最大的values[i] + i,初始值为负无穷大。 -
遍历数组
values,对于每个元素values[j]:- 计算当前的得分
max_i + values[j] - j。 - 更新
max_score如果当前得分更大。 - 更新
max_i_plus_value如果values[j] + j更大。
- 计算当前的得分
-
返回
max_score。
tips:
在C++中,最小值通常可以用 std::numeric_limits<int>::min() 来表示。这个函数返回 int 类型的最小值
话说到这,貌似这个题目还可以用动态规划的方法来写,那具体是怎么样的一个写法呢?
动态规划(Dynamic Programming, DP)是一种通过将问题分解为子问题来解决复杂问题的方法。对于这个问题,我们可以使用动态规划来记录每个位置的最大得分。
动态规划思路
-
定义状态:
- 设
dp[j]表示以第j个景点为结束点的最大得分。
- 设
-
状态转移方程:
- 对于每个
j,我们需要找到一个i(i < j),使得values[i] + values[j] + i - j最大。 - 可以将其分解为两部分:
values[i] + i和values[j] - j。 - 因此,
dp[j] = max(dp[j-1], max(values[i] + i) + values[j] - j),其中i < j。
- 对于每个
-
初始化:
dp[0] = 0,因为以第一个景点为结束点时,没有前面的景点可以组合。
-
最终结果:
- 最终结果为
dp数组中的最大值。
- 最终结果为
ok下面看看完整代码
#include <vector>
#include <iostream>
#include <limits>
#include <bits/stdc++.h>
using namespace std;
int solution(std::vector<int> values) {
int n = values.size();
if (n == 0) return 0;
std::vector<int> dp(n, std::numeric_limits<int>::min());
int max_i_plus_value = std::numeric_limits<int>::min();
for (int j = 0; j < n; ++j) {
if (j > 0) {
dp[j] = max(dp[j-1], max_i_plus_value + values[j] - j);
} else {
dp[j] = 0; // 初始化 dp[0]
}
max_i_plus_value = max(max_i_plus_value, values[j] + j);
}
return *max_element(dp.begin(), dp.end());
}
int main() {
std::cout << (solution({8, 3, 5, 5, 6}) == 11) << std::endl;
std::cout << (solution({10, 4, 8, 7}) == 16) << std::endl;
std::cout << (solution({1, 2, 3, 4, 5}) == 8) << std::endl;
return 0;
}
咳咳,这里我要唠叨一下,*max_element(dp.begin(), dp.end()) 是 C++ 标准库中的一个函数调用,用于在给定的范围内找到最大值。
详细解释
-
max_element函数:max_element是<algorithm>头文件中的一个函数,用于在指定范围内找到最大值。- 它的返回值是一个迭代器,指向范围内最大值的元素。
-
dp.begin()和dp.end():dp.begin()返回指向dp数组第一个元素的迭代器。dp.end()返回指向dp数组最后一个元素之后位置的迭代器。
-
*max_element(dp.begin(), dp.end()):max_element(dp.begin(), dp.end())返回一个迭代器,指向dp数组中的最大值。*操作符用于解引用这个迭代器,获取实际的最大值。