算法第三章
设计一个O(n2)时间的算法,找出由n个数组成的序列的最长单调递增子序列。
输入格式:
输入有两行: 第一行:n,代表要输入的数列的个数 第二行:n个数,数字之间用空格格开
输出格式:
最长单调递增子序列的长度
输入样例:
在这里给出一组输入。例如:
5
1 3 5 2 9
输出样例:
在这里给出相应的输出。例如:
4
#include <iostream>
using namespace std;
int a[10000];
int dp[10000];
int n;
int LIS(){
int ans=1;
for(int i=1; i<=n; i++)//枚举子序列的终点
{
dp[i]=1;// 初始化为1,长度最短为自身
for(int j=1; j<i; j++)//从头向终点检查每一个元素
{
if(a[i]>a[j])
{
dp[i]=max(dp[i],dp[j]+1); // 状态转移
}
}
ans=max(ans,dp[i]); // 比较每一个dp[i],最大值为答案
}
return ans;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
int max=LIS();
cout<<max<<endl;
return 0;
}
状态:d[i] = 长度为i+1的递增子序列的长度
状态转移方程:dp[i] = max(dp[j]+1, dp[i]);
分析:最开始把dp数组初始化为1,然后从前往后考虑数列的元素,对于每个aj,如果a[i] > a[j],就用dp[i] = max(dp[i], dp[j] + 1)进行更新,再从dp数组中找出最大值即为结果
动态规划我认为最重要的是列出状态转移方程,如果满足最优子结构和重复子问题的时候就可以用动态规划的方法去解决