计算由不相邻元素组成的子序列和的最大值

问题描述
给出一个序列 arr ,在 arr 中选择若干个互补相邻的元素组成子序列,计算子序列和的最大值

方法1 —— 递归实现

  1. 考虑使用 递归,定义rect_func(i)为子序列所有元素均在元素arr[i]之前时,子序列的最大值
  2. 递归终止条件为i == 0 或 i == 1
  3. rect_func(i) = max(rect_func(i-2) + arr[i], rect_func(i-1)),其中rect_func(i-2) + arr[i]代表选择了元素arr[i], rect_func(i-1)代表未选择元素arr[i](因此可以选择arr[i-1],问题变为rect_func(i-1))

程序设计

int rect_opt(const int a[], int i){
	if (i == 0) return a[0];
	if (i == 1) return std::max(a[0], a[1]);
	int A = rect_opt(a, i-2) + a[i];
	int B = rect_opt(a, i-1);
	return std::max(A, B); 
}

其中,传入的a[]为原始数组,i表示以在元素arr[i]之前选择子序列。


方法1 —— 动态规划
由于当初始序列很长时, 递归调用要计算很多重叠子问题,占用太多内存,计算速度慢,考虑用数组来存储每个子问题的结果 —— 动态规划实现。

  1. 状态转移方程为:dp(i) = max(dp(i-2) + arr[i], dp(i-1)),dp(i)表示子序列各个元素均在arr[i]之前
  2. 先初始化 dp[0] 和 dp[1]
  3. 循环计算dp的所有值

程序设计

int dp_opt(const int a[], int n){
	if (n == 1) return a[0];
	else if (n == 2) return max(a[0], a[1]);
	int dp[n];
	dp[0] = a[0];
	dp[1] = max(a[0], dp[1]);
	for (int i=2; i<n; i++){
		dp[i] = max(dp[i-1], dp[i-2] + a[i]);
	}
	return dp[n-1];
}

结果

int main()
{
	int n = 7;
	int a[n] = {1, 2, 4, 1, 7, 8, 3};
	cout << rect_opt(a, 6) << endl;
	cout << dp_opt(a, n);
	return 0;
}

此时输出结果为:15,选择的序列为 {1, 4, 7, 3},正确!

在这里插入图片描述

问题:如何输出被选择的元素?
解答:获取动态规划的整个数组(所有记录),从后往前,用当前opt[i]与opt[i-2] + arr[i]作比较,若相等则说明 arr[i] 被选了。


参考内容: 动态规划

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值