【动态规划常用解题思路】

        动态规划相信大家都很熟悉,但也是一个难点,对于动态规划,我也写出了我的一些观点,其中我会拿(最长不下降子序列,最长公共子序列,前缀和最大值)这些比较经典的动态规划题,来表明我的观点,开始!!!!!!!!!

1794 - 最长不下降子序列(LIS)

题目描述

设有由n个不相同的整数组成的数列,记为: a(1)、a(2)、……、a(n)且a(i)<>a(j)  (i<>j)。例如3,18,7,14,10,12,23,41,16,24。若存在i1<i2<i3<… < ie且有a(i1)<a(i2)<…  <a(ie)则称为长度为e的不下降序列。如上例中3,18,23,24就是一个长度为4的不下降序列,同时也有3,7,10,12,16,24长度为6的不下降序列。程序要求,当原数列给出之后,求出最长的不下降序列。

输入

第一行为n,表示n个数(10<=n<=10000)
第二行n个整数,数值之间用一个空格分隔(1<=a(i)<=n)

输出

最长不下降子序列的长度

样例

输入

复制

3
1 2 3
输出

复制

3

首先,我们知道,动态规划的题目无非就是贪心 + 递推,我们要知道dp数组表达的意思,(读者可以先想一想)也就是dp[i] = 表示以a[i]为结尾的最长不下降子序列;那么,dp数组表达意思知道了,便可以开始找递推的边界,可以结合题目得知以a[1]为结尾的最长不下降子序列为1,也就是dp[1] = 1;确定这两项后,便可以开始确定状态转移方程了,我们可以去想一想,dp[i] 如何从dp[i-1]dp[i-2] dp[i-3]......推出呢?我们可以用两个循环来写,一个从2开始到n,一个从1开始到i,如果a[i] > a[j] 时,dp[i] = max(dp[i],dp[j]+1);

扫描二维码关注公众号,回复: 17338193 查看本文章

看代码:

dp[1] = 1;
for(int i = 2;i<=n;i++){
    for(int j = 1;j<=i;j++){
        if(a[i] > a[j]) dp[i] = max(dp[i],dp[j]+1);
    }
}

确定转移方程后,就要确定最终的答案在哪儿,很容易看出,给dp打个擂台就行了:

int sum = INT_MIN;
for(int i = 1;i<=n;i++) sum = max(dp[i],sum);

如果你全部理解,恭喜你,你已经很厉害了,好了,时间也不早了,看完整代码:

#include<bits/stdc++.h>
using namespace std;
int n;
int a[10010];
int f[10010]; 
int mx = -1; 
int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		f[i]=1; 
	}
	for(int i=2;i<=n;i++){
		for(int j=1;j<=i;j++){
			if(a[i]>=a[j])
				f[i]=max(f[i],f[j]+1);
		}
	}
	for(int i=1;i<=n;i++){
		mx=max(mx,f[i]);
	}
	printf("%d",mx);
	return 0;
}

后续我会继续更新,下次见

猜你喜欢

转载自blog.csdn.net/nihaoxingshijie/article/details/134621256
今日推荐