Codeforces [10D] LCIS [subsecuencia ascendente común más larga]

Descripción

La secuencia  a 1,  a 2, ...,  a n  se llama creciente, si  a i  <  a i  + 1 para  i  <  n .

La secuencia  s 1,  s 2, ...,  s k  se llama subsecuencia de la secuencia  a 1,  a 2, ...,  a n , si existe tal conjunto de índices 1 ≤  i 1 <  i 2 < ... <  i k  ≤  n  que  a i j  =  s j . En otras palabras, la secuencia  s  se puede derivar de la secuencia  a  tachando algunos elementos.

Te dan dos secuencias de números enteros. Debe encontrar su subsecuencia creciente común más larga, es decir, una secuencia creciente de longitud máxima que es la subsecuencia de ambas secuencias.

Entrada 

La primera línea contiene un número entero  n  (1 ≤  n  ≤ 500), la longitud de la primera secuencia. La segunda línea contiene  n  enteros separados por espacios del rango [0, 10 ^ 9] - elementos de la primera secuencia. La tercera línea contiene un número entero  m  (1 ≤  m  ≤ 500), la longitud de la segunda secuencia. La cuarta línea contiene  m  enteros separados por espacios del rango [0, 10 ^ 9] - elementos de la segunda secuencia.

Salida 

En la salida de la primera línea  k  , la longitud de la subsecuencia creciente común más larga. En la segunda línea sale la subsecuencia misma. Separar los elementos con un espacio. Si hay varias soluciones, envíe cualquiera.

Ejemplos

entrada

7
2 3 1 6 5 4 6
4
1 3 5 6

salida

3
3 5 6  

 entrada

5
1 2 0 2 1
3
1 0 1

 salida

2
0 1 

La idea principal:

Dadas las matrices A y B cuya longitud es menor o igual a 500, encuentre su subsecuencia ascendente común más larga. 

Análisis:

dp [i, j] Expresado  A_1 ... A_i y  B_1 ... B_j estar compuesto de  B_j una longitud de la CLIS final.

Cuando  A_i \ neq B_j el tiempo tiene dp [i, j] = dp [i-1, j]

Cuando  A_i = B_j el tiempo tiene dp [i, j] = \ max_ {0 \ leq k <j, B_k <B_j} (dp [i-1, k]) + 1

Aquí, porque al enumerar k, se O (n ^ 3) agota el tiempo de espera, así que optimícelo.

Record [0, todo j),  B_k <B_jel  dp [i-1, k]valor máximo utilizado para consulta directamente, a continuación, ponemos i como el bucle más externo, mantener constantemente este máximo, entonces se puede poner la complejidad el tiempo de inactividad  O (n ^ 2).

Vea el código para una explicación específica.

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 500 + 5;

int dp[maxn][maxn],p[maxn][maxn];
int a[maxn],b[maxn];
vector<int> v;
int n,m,ans,path;

void LCIS(int a[],int n,int b[],int m){
    for(int i=1;i<=n;i++){//外层循环
        int maxlen=0,pre=0;//maxlen代表dp[i-1][k]中的最大值,pre代表当前maxlen下的前一个B序列中选出的值(记录路径)
        for(int j=1;j<=m;j++){
            //这里假设Ai和Bj不等
            dp[i][j]=dp[i-1][j];
            p[i][j]=p[i-1][j];
            if(a[i]==b[j]&&dp[i][j]<maxlen+1){//更新dp[i][j]和p[i][j]
                dp[i][j]=maxlen+1;
                p[i][j]=pre;
            }
            if(b[j]<a[i]&&dp[i-1][j]>maxlen){//更新maxlen和pre
                maxlen=dp[i-1][j];
                pre=j;
            }
        }
    }
}

void Print(int pa) {//打印路径
    if(!pa) return;
    Print(p[n][pa]);
    cout<<b[pa]<<" ";
}

int main() {
    memset(dp,0,sizeof(dp));
    memset(p,0,sizeof(p));
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        scanf("%d",&b[i]);
    }
    LCIS(a,n,b,m);
    //选出最长路径
    for(int i=1;i<=m;i++){
        if(ans<dp[n][i]){
            ans=dp[n][i];
            path=i;
        }
    }
    printf("%d\n",ans);
    Print(path);
    return 0;
}

 

30 artículos originales publicados · ganó 5 · 900 visitas

Supongo que te gusta

Origin blog.csdn.net/qq_42840665/article/details/104055450
Recomendado
Clasificación