版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LZUwujiajun/article/details/81355225
概览
一个问题必须有重叠子问题和最优子结构(这个问题的最优解可以由其子问题的最优解有效的构造出来)才可以用动态规划解决。
解决方式:
- 递推:自底向上
- 递归自顶向下
贪心与动态规划的区别
贪心是局部最优解,在每一次选择中,选了就不后悔。动态规划则考虑所有的子问题,选择能笑到最后的。
数塔问题
//数塔问题,将一些数字排成塔状,第n层有n个数字,现在从第一层走到第n层
//最后路径上最大的数字之和为多少
//用DFS做复杂度O(2^n),存在大量的重复子问题
//状态转移方程:dp[i][j] = max(dp[i+1][j],dp[i+1][j+1])+f[i][j]
#include<cstdio>
#include<algorithm>
using namespace std;
int f[1000][1000] = {0};
int dp[1000][1000] = {0};
int main(){
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++){
for(int j = 1; j <= i;j++){
scanf("%d",&f[i][j]);
}
}
for(int j = 1;j <= n;j++){
dp[n][j] = f[n][j];
}
for(int i = n-1;i >=1;i--){
for(int j = 1;j <= i;j++){
dp[i][j] = max(dp[i+1][j],dp[i+1][j+1])+f[i][j];
}
}
printf("%d",dp[1][1]);
}
最大连续子列和
//最大连续子序列和
//dp[i]表示以i结尾的数列的最大值
//状态转移方程 dp[i] = max(arr[i],dp[i-1]+arr[i])
#include<cstdio>
#include<algorithm>
using namespace std;
int main(){
int arr[] = {-2,11,-4,13,-5,-2};
int dp[6];
dp[0] = arr[0];
for(int i = 1;i < 6;i++){
dp[i] = max(arr[i],dp[i-1]+arr[i]);
}
int maxSum = -1;
for(int i = 0;i < 6;i++){
if(dp[i] > maxSum){
maxSum = dp[i];
}
}
printf("%d",maxSum);
}
最长不下降子序列
//最长不下降子序列
//状态转移方程dp[i] = max(1,dp[j]+1),条件:arr[j] <= arr[i] && dp[j]+1>dp[i]
//时间复杂度O(n^2)
#include<cstdio>
#include<algorithm>
using namespace std;
int main(){
int n;
scanf("%d",&n);
int arr[1000],dp[1000];
for(int i = 0;i < n;i++){
scanf("%d",&arr[i]);
}
int ans = -1;
for(int i = 0;i < n;i++){
dp[i] = 1;
for(int j = 0;j < i;j++){
if(arr[j] <= arr[i] && dp[j]+1>dp[i]){
dp[i] = dp[j]+1;
}
}
ans = max(ans,dp[i]);
}
printf("%d",ans);
}
最长公共子序列
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
//最长公共子序列
//d[i][j]表示A的i号位和B的j号位之前的最长公共子序列
//d[i][j] = dp[i-1][j-1]+1;A[i] = b[i]
//d[i][j] = max(dp[i-1][j],dp[i][j-1]);A[i] != b[i]
int main() {
int dp[100][100];
string A = " sadstory";
string B = " adminsorry";
int lenA = A.size()-1;
int lenB = B.size()-1;
for(int i = 0;i <= lenA;i++){
dp[i][0] = 0;
}
for(int i = 0;i <= lenB;i++){
dp[0][i] = 0;
}
for(int i = 1;i <= lenA;i++){
for(int j = 1;j <= lenB;j++){
if(A[i] == B[j]){
dp[i][j] = dp[i-1][j-1]+1;
}else{
dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
}
}
}
printf("%d",dp[lenA][lenB]);
}