算法:动态规划——线性DP(C++)

  • 博客主要参考书:胡凡《算法笔记》

概述

在我看来动态规划就是将一个问题的最优问题分解为子问题的最优解来获得真正的最优解。动态规划问题当中重要的就是:

  • 状态的转化方程:目标态=F(某一状态)。
  • 有边界状态和其值

使用条件:1.有重复的子问题;2.有最优子结构

经典的问题

1.最大连续子序列和

题目:给定一个序列:S1,S2,S3…Sn,有i,j使得sum=Si+Si+1…+Sj-1+Sj最大,求最大值。
这很明显是一个最优解问题,同时我们在考虑当前的数
我们设数组dp[n]当中存放的是以当前的i,即dp[i]是以Si为结尾的最大连续子列的。那么对于dp[i]有两种情况:

  • 将Si放入前序列:dp[i]=dp[i-1]+Si
  • Si不放入前序列:dp[i]=Si,即此时以Si结尾的最大序列和就是以Si开头的。

所以dp[i]=max(dp[i-1]+Si,Si),也就是我们的状态转换方程,现在的状态可以由另一个状态转换而来。
边界:dp[1]=S1;
当我们获得dp数组的所有值之后,也就意味着我们获得了以每一个数字结尾的连续子序列的最大和,再次遍历选出其中最大的值,就是我们需要的结果(我们并不需要知道这个连续序列是谁,只要他的值就可以)
代码如下:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1010;
int S[N], dp[N];
int main() {
   
	int n;
	cin >> n;//读入序列的个数
	for (int i = 0; i < n; i++) {
   
		cin >> S[i];//读入序列
	}
	dp[0] = S[0];//边界条件
	for (int i = 1; i < n; i++) {
   
		//状态转换方程
		dp[i] = max(S[i], dp[i - 1] + S[i]);
	}
	//找出最大的
	int Max_sum = 0;
	for (int i = 0; i < n; i++) {
   
		Max_sum = max(Max_sum, dp[i]);
	}
	cout << Max_sum;
	return 0;
}

2.最长不下降子序列

问题:给定一个序列:S1,S2,S3…Sn,找到一个最长的子序列,可以是不连续的,使得其是不下降的序列(非递减的),求此序列的长度。
这题先直接给出代码,然后对比上一题的不同进行分析:
代码࿱

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值