题目:
纯粹最长上升子序列(lis:Longest Increasing Subsequence)
状态转移方程(时间复杂度为O(n*n))
if(a[i]<a[j])
dp[i]=Max(dp[i],dp[j]+1);
解一:
根据状态转移方程:
if(a[i]<a[j])
dp[i]=Max(dp[i],dp[j]+1);
#include <iostream>
#include <cstring>
using namespace std;
#define X 1003
int dp[X];
int a[X];
int Max(int a,int b)
{
return a>b?a:b;
}
int main()
{
freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
int n;
while(cin>>n)
{
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=n;i>=1;i--)
for(int j=i+1;j<=n;j++)
if(a[i]<a[j])
dp[i]=Max(dp[i],dp[j]+1);//核心算法
int max = 0;
for(int i=0;i<=n;i++) //找出最大的上升子序列
if(max<dp[i])
max = dp[i];
cout<<max+1<<endl;
}
return 0;
}
解二:
O(n^2)算法分析如下: (num[1]...num[n] 存的都是输入的数)
1、对于num[n]来说,由于它是最后一个数,所以当从num[n]开始查找时,只存在长度为1的不下降子序列;
2、若从num[n-1]开始查找,则存在下面的两种可能性:
(1)若num[n-1] < num[n] 则存在长度为2的不下降子序列 num[n-1],num[n].
(2)若num[n-1] > num[n] 则存在长度为1的不下降子序列 num[n-1]或者num[n]。
3、一般若从num[j]开始,此时最长不下降子序列应该是按下列方法求出的:
在a[j+1],a[j+2],...a[n]中,找出一个比a[t]大的且最长的不下降子序列,作为它的后继。
4、为算法上的需要,定义两个数组: num[MAX]存数lis[MAX]从i开始的最大上升子序列的长度
也可以:
d:array [1..n,1..3] of integer;
d[t,1]表示a[t]
d[t,2]表示从i位置到达n的最长不下降子序列的长度
d[t,3]表示从i位置开始最长不下降子序列的下一个位置
#include <iostream>
#include <cstring>
using namespace std;
#define X 1003
int dp[X];
int a[X];
int Max(int a,int b)
{
return a>b?a:b;
}
int main()
{
freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
int n;
while(cin>>n)
{
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
cin>>a[i];
int ans = 0;
for(int i=n;i>=1;i--)
{
int max = 0;
for(int j=i+1;j<=n;j++)
if(a[i]<a[j]&&dp[j]>max)
max = dp[j];
dp[i] = max+1;
if(dp[i]>ans)
ans = dp[i];
}
cout<<ans<<endl;
}
return 0;
}