C++ 中,必须求前缀和前缀后给定元素的最大和递增子序列
c++server side programmingprogramming
在这个问题中,我们给定一个包含 N 个整数的数组 arr[] 和两个索引值 x 和 y。我们的任务是编写一个程序,根据前缀和前缀后给定元素,求出最大和的递增子序列。在 C++ 中,前缀和前缀后给定元素是必须的。
问题描述
我们将求出直到索引 x 的递增序列的最大和,包括索引 y 处的元素。
让我们举个例子来理解这个问题:
输入
arr[] = {1, 5, 9, 131, 6, 100, 11, 215}, x = 4, y = 6
输出
26
解释
我们将取直到索引 3 的子序列,最后包括 arr[6] = 11.
子序列为 {1, 5, 9, 11}。总和 = 1+5+9+11 = 26
解决方法
一种简单的方法是创建一个到 x 索引的新数组,然后将索引 y 处的元素添加到末尾。然后计算所有递增子序列,丢弃所有不包含元素 arr[y] 的子序列,并找到最大和。
另一种更有效的解决方法是使用动态规划方法。其思路是创建一个二维数组 DP[][],并存储递增子序列的最大和。DP[x][y] 处的值将给出到索引 x 处包含元素 arr[y] 的最大和。
示例
编写程序说明我们的解决方案的工作原理
#include <iostream> using namespace std; int DP[100][100]; void preCalcMaxSum(int arr[], int N){ for (int i = 0; i < N; i++) { if (arr[i] > arr[0]) DP[0][i] = arr[i] + arr[0]; else DP[0][i] = arr[i]; } for (int i = 1; i < N; i++) { for (int j = 0; j < N; j++) { if (arr[j] > arr[i] && j > i) { if (DP[i - 1][i] + arr[j] > DP[i - 1][j]) DP[i][j] = DP[i - 1][i] + arr[j]; else DP[i][j] = DP[i - 1][j]; } else DP[i][j] = DP[i - 1][j]; } } } int main() { int arr[] = {1, 5, 9, 131, 6, 100, 11, 215}; int N = sizeof(arr) / sizeof(arr[0]); int x = 4, y = 6; preCalcMaxSum(arr, N); cout<<"前缀和前缀后给定元素的最大和为 <; cout<<DP[x][y]; return 0; }
输出
前缀和前缀后给定元素的最大和为 26
一种高效方法是求出到索引 x 的递增子序列的最大和,使得序列中的最大元素小于索引 y 处的元素。为此,我们将再次使用动态规划方法。
示例
程序演示我们的解决方案
#include <iostream> using namespace std; int calcMaxSum(int arr[], int n, int x, int y){ int DP[x] = {0}; int maxSum = -1; for (int i = 0; i <= x; i++) DP[i] = arr[i]; for (int i = 0; i <= x; i++) { if (arr[i] >= arr[y]) { continue; } for (int j = 0; j < i; j++) { if (arr[i] > arr[j]) DP[i] += arr[j]; maxSum = max(maxSum, DP[i]); } } if (maxSum == -1) { return arr[y]; } return maxSum + arr[y]; } int main(){ int arr[] = {1, 5, 9, 131, 6, 100, 11, 215}; int N = sizeof(arr) / sizeof(arr[0]); int x = 4, y = 6; cout<<"前缀和前缀后的给定元素的最大和递增子序列必须是 "; cout<<calcMaxSum(arr, N, x, y); return 0; }
输出
前缀和前缀后的给定元素的最大和递增子序列必须是 26