1. 程式人生 > 其它 >acwing 895. 最長上升子序列

acwing 895. 最長上升子序列

給定一個長度為 N 的數列,求數值嚴格單調遞增的子序列的長度最長是多少。

輸入格式
第一行包含整數 N。

第二行包含 N 個整數,表示完整序列。

輸出格式
輸出一個整數,表示最大長度。

資料範圍
1≤N≤1000,
−109≤數列中的數≤109
輸入樣例:
7
3 1 2 1 8 5 6
輸出樣例:
4

錯誤的做法,

這個做法錯誤的原因是:列舉以a[i]為開始的上升序列無法找到最長的,比如 1 2 8 5 6, 下面的做法以1開始只能找到1 2 8,所以列舉以a[i]開始的最長子序列行不通,所以想到 看以a[i]為結尾的最長子序列,從而想到下一個動態規劃的做法

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;

const int N = 1010;
int a[N], f[N];
int n;

int main()
{
    // 暴力做法
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    
    int res = 0;
    for(int i = 1; i <= n; i++)
    {
        int p = 1;
        int t = a[i];
        for(int j = i+1; j <= n; j++)
        {
            if(a[j] > t)
            {
                t = a[j];
                p++;
            }
        }
        
        res = max(res, p);
    }
    cout << res << endl;
    return 0;
}

正確做法

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;

const int N = 1010;
int a[N], f[N];
int n;

int main()
{
  // f[i]表示以a[i]結尾的最長上升子序列的長度
  // f[i] = max(f[j]) + 1 (if a[j] < a[i])
  
  scanf("%d", &n);
  for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
  
  // 初始化
  for(int i = 1; i <= n; i++) f[i] = 1;
  
  for(int i = 1; i <= n; i++)
  {
      for(int j = 1; j < i; j++)
      {
          if(a[j] < a[i]) f[i] = max(f[i], f[j] + 1);
      }
  }
  
  int res = 0;
  for(int i = 1; i <= n; i++) 
  {
      res = max(res, f[i]);
  }
  
  printf("%d", res);
  return 0;
}

時間複雜度為\(O(n^2)\)

如何將最長子序列儲存下來