最大上升子序列之和

题目

题目中已告诉最长上升子序列之和!=最大上升子序列之和

动态规划的比较重要的点

1. 拆分成子问题
2. 状态转移方程

(其实动态规划也可以理解为递归的逆过程)

根据这道题来实操一下

  1. 拆分成子问题

    求的是n个数的最大上升子序列之和
    则可以拆分成求n-1个数的最大上升子序列之和
    以此类推 最后是先求1个数的最大上升子序列之和
    //这里是做题自己想
    (这里有没有一点递归的味道,1为返回条件)
    从求当一个数时到求当两个数时的最大上升子序列之和
    以此类推,最后由求当n-1时到当n时的最大上升子序列之和
    //这里是程序进行求解
    (有没有递归返回去的味道)

  2. 状态转移方程

    状态转移方程,是连接两个状态的桥梁

    可能这样说比较抽象,结合这道题来理解一下
    求当一个数时到求当两个数时的最大上升子序列之和,再到三个数时
    简单模拟一下
    这里有两个数组

    int ans[1000+10]={0,1,50,20,72};//存储和
    int m[1000+10]={0,1,50,20,72};//存数的序列
    

    假设
    这四个数是:1 50 20 72
    求一个数时 自然和为1;
    那么ans[1]=1;
    两个数时
    首先要判断是不是上升序列
    这里是true,和为50+1;
    ans[2]==ans[1]+m[2]==21;//原本ans[2]=50;
    三个数时
    m[1]与m[3]能成为上升序列—>ans[3]=ans[1]+ans[3]//ans[3]原本为20
    四个数时
    m[4]与m[2]能成为上升序列—>ans[4]=ans[2]+m[4]
    总结一下
    如果是上升序列,比较(当前值m+序列前一个数的上升子序列的和ans,当前值ans)
    不能比较成m+ans,m;

  • 从数据的角度出发相加一定大于原数,会导致最终答案错误
  • 从处理时的角度出发,如果盲目的先加前面的数,会导致后面应该加的更大的数加不了

AC code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;
int n;
long long ans[1000+2];
int m[1000+2]; 
int main(){
	cin>>n;
	for(int i=1;i<=n;++i){
		cin>>m[i];
		ans[i]=m[i];//因为求的是最大上升子序列之和,所以他本身为一个数的时候,最大上升子序列和为他本身
	} 
	for(int i=2;i<=n;++i)
		for(int j=1;j<i;++j)//首先要满足是以i为终点的值大于j的值,保证是上升子序列 
			if(m[i]>m[j]) ans[i]=max(ans[i],m[i]+ans[j]);//比较目前以i为终点上升子序列之和的值,和以j为终点的值+i的值
			//谁大谁为最大上升子序列之和的值
	sort(ans+1,ans+1+n);
	cout<<ans[n]; 
	return 0;
} 

解释不佳,还请指出
解释有误,还请纠正

posted @ 2021-02-02 15:31  归游  阅读(105)  评论(0编辑  收藏  举报