동적 프로그래밍 전달 방정식을 이해할 수 없습니까? 내가 설명한 가장 긴 상승 부분 수열의 관점에서 문제 분석

머리말

동적 프로그래밍과 같은 문제는 항상 모든 사람이 알고리즘 학습에서 접하는 가장 어려운 문제 중 하나였습니다. 한 종류의 문제는 선형 DP라고도 하는 선형입니다. 오늘은 가장 긴 오름차순 부분수열 I을 분석해 보겠습니다.

주제 정보

给定一个长度为 N 的数列,求数值严格单调递增的子序列的长度最长是多少。

참고: 여기에서 하위 시퀀스 요구 사항은 엄격하게 단조 증가합니다. 예를 들어 1, 2, 3, 4. 1, 1, 2, 3, 4가 될 수 없습니다.


입력 형식

第一行包含整数 N。
第二行包含 N 个整数,表示完整序列。

출력 형식

输出一个整数,表示最大长度。

데이터 범위

이 질문의 데이터 범위:
1≤N≤100000, −109≤数列中的数≤109
알고리즘 질문의 주요 목적은 알고리즘이 수행될 수 있다는 전제 하에 알고리즘의 시간 복잡도를 최적화하는 것이므로 질문의 데이터 범위는 주의가 필요한 지점입니다.

견본

입력하다:
7 3 1 2 1 8 5 6

산출:
4

아이디어

원래 분석 아이디어의 저자: Yan Xuecan. 웹사이트AcWing

여기에 이미지 설명 삽입
제가 잘 이해하지 못하는 사진이 하나 있을 수 있습니다. 예를 들어보겠습니다.

3 1 2 1 8 5 6

설명:
集合:상태가 나타내는 집합은 특정 숫자로 끝나는 집합을 의미합니다. 예를 들어, 숫자 8의 집합은 {1,8}, {3,8}, {2,8}, {1,8}을 포함합니다.

属性:그러나 f[i]는 구체적인 값입니다. 이 값은 이러한 집합 중 가장 긴 집합 길이를 나타냅니다. 여기 2가 있습니다.

状态计算:각 집합은 i번째 숫자로 끝나므로 각 숫자에는 숫자 i가 포함됩니다. 아래의 타원은 i-1번째 숫자에서 이러한 집합을 클래스로 나누는 것을 나타냅니다.

첫 번째 유형: i-1번째 숫자가 0, 즉 부분 수열의 길이가 1이고 i-1번째 숫자가 없습니다
. 두 번째 유형: i-1번째 숫자가 1이고, 가장 긴 오름차순 부분 수열의 길이는 i-1+ i, 즉 f[1]+1입니다
. 세 번째 유형: i-2번째 숫자는 2이고 가장 긴 오름차순 부분 수열의 길이는 i-2+ i입니다. , 즉, f[2 ]+1
...
i-1th: i-1번째 숫자는 i-1이고 가장 긴 오름차순 부분 수열의 길이는 i-1+ 1입니다. 즉, f[i-1 ]+1

이러한 시퀀스는 가장 긴 오름차순 부분 시퀀스이기 때문에 반드시 존재하는 것은 아니므로 [i]>a[j]도 충족되어야 합니다. i는 마지막 숫자이므로 j는 그보다 작아야 합니다.

글쎄, 그것에 대해 생각한 후에 코드 작성을 시작할 수 있습니다.

암호

import java.util.Scanner;
public class Main {
    
    
    static  int N=1010;
    //题目给的子序列
    static  int a[]=new int[N];
    //状态表示的数组
    static  int f[]=new int[N];
    public static void main (String[] args) {
    
    
        Scanner sc=new Scanner (System.in);
        int n=sc.nextInt ();
        for (int i = 1 ; i <=n  ; i++) {
    
    
            a[i]=sc.nextInt ();
        }
        //f[i]表示最长上升子序列的最大长度
        for (int i = 1 ; i <=n  ; i++) {
    
    
            f[i]=1;
            //f[i]=1  这时只有i一个数,所以f[1]=1;
            for (int j = 1 ; j <i  ; j++) {
    
    
              if(a[j]<a[i]){
    
    
                    f[i]=Math.max (f[i],f[j]+1);
                }
            }
        }
        //求出所有f的集合后,在遍历一遍f,求出最长的子序列的长度。
        int res=0;
        for (int i = 1 ; i <=n  ; i++) {
    
    
            res=Math.max (res,f[i]);
        }
        System.out.println (res);
    }
}

추천

출처blog.csdn.net/guankunkunwd/article/details/123632138