最长上升(也有译作递增)子序列问题简称LIS(Longest Increasing Subsequence)问题,其数学模型如下:
设A = 是n个不同的实数的序列,A的上升子序列是这样的一个子序列L =< >,
其中且。求最大的m值。
一共有三种DP方法 可用于最长上升子序列问题
设序列X = <>是对序列A = 按上升序列排好序的序列。显然X和A的最长公共子序列就是A的最长上升序列。这个原理比较简单就直接给出代码。
#include
using namespace std;
int dp[10][10];
int A[] = {1, 7, 3, 5, 9, 4, 8},X[7];
void dp_lcs() {
for(int i = 0 ; i < 7; i++) {
dp[i][0] = 0;
dp[0][i] = 0;
}
for(int i = 1 ; i <= 7; i++) {
for(int j = 1 ; j <= 7; j++) {
if(A[i-1] == X[j-1])
dp[i][j] = dp[i-1][j-1]+1;
else
dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
}
}
}
int main() {
for(int i = 0 ; i < 7; i++) {
X[i] = A[i];
}
sort(A,A+7);
//开始LCS
dp_lcs();
for(int i = 1 ; i <= 7; i++) {
for(int j = 1; j <= 7; j++) {
cout<
首先确定状态,求什么就设什么,dp[i]代表第i个元素时的LIS长度。
当前的LIS长度肯定是,其子序列的LIS的长度+1,这就证明了LIS的最优子结构特征。
#include
#include
#include
#include
using namespace std;
int dp[100010];
int a[100010];
int ans = 1;
int main(){
int n,maxx = 0,k;
scanf("%d",&n);
for(int i = 1; i <= n; i++)
scanf("%d",a+i);
/*************核心部分*****************/
for(int i = 1; i <= n; i++){
dp[i] = 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]);
}
/*************************************/
cout<
第二种DP方法在计算么一个dp[i]时,都要找出最大的dp[j](1 <= j
这里使用一个辅助数组b来存储子序列的LIS,b[len]存的就是LIS的尾元素(即最大的元素)。
1.当b[len] < a[i]:说明a[i]能接在d[len]后面,长度增加,直接 b[++len] = a[i];
2.否则,找到 b(LIS)中第一个大于等于a[i]的元素 b[k],令 b[k] = a[i],b[1] 的初始值为 a[1],len初始值为1。
3.最终的len就是我们要求的答案。
举个栗子:
5
19 11 10 7 8
初始化 len = 1,b[1] = a[1] = 19,LIS = {19};
i = 2时,a[2] < b[len(1)],找到第一个大于等于a[2]的元素b[1] = 19,使b[1] = 11;
i = 3时,a[3] < b[len(1)],找到第一个大于等于a[3]的元素b[1] = 11,使b[1] = 10;
i = 4时,a[4] < b[len(1)],找到第一个大于等于a[3]的元素b[1] = 10,使b[1] = 7;
i = 5时,a[5] < b[len(1)],len++,使b[len(2)] = a[5]。
len = 2,算法结束。
#include
#include
#include
#include
using namespace std;
int dp[100010];
int a[100010],b[100010];//b用来保存LIS
int ans = 1;
int main() {
freopen("data.in","r",stdin);
int n,maxx = 0,k;
scanf("%d",&n);
for(int i = 1; i <= n; i++)
scanf("%d",a+i);
/*核心部分******************************/
int len = 1;
b[1] = a[1];
for(int i = 2; i <= n; i++) {
if(b[len] <= a[i])
b[++len] = a[i];
else
*lower_bound(b+1,b+len,a[i]) = a[i];//此处使用了STL优化 lower_bound本身就是用二分法封装的
}
/*************************************/
cout<<"max:"<