求最长不下降子序列 简单动态规划问题
题目
求最长不下降子序列
描述
设有由n(1≤n≤200)个不相同的整数组成的数列,记为:b(1)、b(2)、……、b(n)b(1)、b(2)、……、b(n)且b(i)≠b(j)(i≠j)b(i)≠b(j)(i≠j),若存在i<i2<i3<…<iei1<i2<i3<…<ie且有b(i1)<b(i2)<…<b(ie)b(i1)<b(i2)<…<b(ie)则称为长度为e的不下降序列。程序要求,当原数列出之后,求出最长的不下降序列。
例如13,7,9,16,38,24,37,18,44,19,21,22,63,15。
例中13,16,18,19,21,22,63就是一个长度为7的不下降序列,
同时也有7 ,9,16,18,19,21,22,63组成的长度为8的不下降序列。
输入格式
第一行为n,第二行为用空格隔开的n个整数。
输出格式
第一行为输出最大个数max(形式见样例);
第二行为max个整数形成的不下降序列,该题保证序列唯一
输入样例
14
13 7 9 16 38 24 37 18 44 19 21 22 63 15
输出样例
max=8
7 9 16 18 19 21 22 63
题目思路
简单的动态规划,简单推出状态转移方程,再利用dp数组即可。
#include <iostream>
#include <string.h>
using namespace std;
int ans[200];int Max=0,Max_f;int n,a[1000]={},dp[1000]={},tot=0;
void findans(int Max_f){
//cout<<Max_f<<endl;
if(ans[Max_f]==-1){
return;
} //终止条件
else {
findans(ans[Max_f]);
cout<<a[ans[Max_f]]<<" ";
} //输出
return ;
}
int main(){
memset(ans,-1,sizeof(ans)); //数组归零
cin>>n; //输入
for(int i=0;i<n;i++){
cin>>a[i]; dp[i]=1;
}
for(int i=1;i<n;i++){
for(int j=0;j<i;j++)
if(a[j]<=a[i]){
if(dp[j]+1>dp[i])
ans[i]=j; //记录前一个位置
dp[i]=max(dp[j]+1,dp[i]); //状态转移方程
}
}
for(int i=0;i<n;i++){
if(dp[i]>Max){
Max=dp[i];
Max_f=i;
}
} //找出Max和Max的位置
cout<<"max="<<Max<<endl; //输出
findans(Max_f); //递归输出
cout<<a[Max_f]<<endl; //防止末尾空格
return 0;
}
代码仅供参考,让我们共同学习!