codeforces 463D D. Gargari and Permutations(dp)

4771 단어 dpcodeforces정렬

제목 링크:


codeforces 463D

제목 대의:


k개의 배열을 보여 주십시오. 이 k개의 배열의 가장 긴 공통 서열의 길이를 물어보십시오.

제목 분석:

  • 처음으로 이런 배열의 dp를 만들었는데 새로운 정의 상태의 방법을 배운 것 같다.
  • 우선pos[i][j]는 i행수 j가 나타난 위치를 기록해야 한다.
  • cnt[i]는 현재 스캔한 범위 내의 i 출현 횟수를 기록합니다.
  • dp[i]는 i로 끝나는 가장 긴 공공 서열의 길이를 나타낸다.
  • 우리가 먼저 서열의 길이를 훑어본 다음에 매 줄의 수를 스캔해서 cnt[i]를 업데이트한 다음에 cnt[i]==k를 훑어보면 전 j열을 이용하여 i로 끝나는 공공 서열을 얻을 수 있음을 증명한다. 그러면 우리는 이미 업데이트된 k를 훑어보고 모든 줄에pos[j]>pos[k]를 만족시키면 dp[i]=max(dp[i], dp[k]+1)
  • 를 업데이트할 수 있다.
  • 마지막 매거가 개수로 끝나는 경우 가장 큰 상황을 판단하면 된다.

  • AC 코드:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <algorithm>
    #define MAX 1007
    
    using namespace std;
    
    int n,k;
    int dp[MAX];
    int pos[MAX][MAX];
    int a[MAX][MAX];
    int cnt[MAX];
    vector<int> ans;
    
    int main ( )
    {
        while ( ~scanf ( "%d%d" , &n , &k ) )
        {
            ans.clear();
            for ( int i = 1 ; i <= k ; i++ )
                for ( int j = 1 ; j <= n ; j++ )
                    scanf ( "%d" , &a[i][j] );
            for ( int i = 1 ; i <= k ; i++ )
                for ( int j = 1 ; j <= n ; j++ )
                    pos[i][a[i][j]] = j;
            memset ( dp , 0 , sizeof ( dp ) );
            memset ( cnt , 0 , sizeof ( cnt ) );
            ans.push_back ( 0 );
            for ( int i = 1 ; i <= n ; i++ )
                for ( int j = 1 ; j <= k ; j++ )
                {
                    int x = a[j][i];
                    cnt[x]++;
                    if ( cnt[x] == k )
                    {
                        for ( int t = 0 ; t < ans.size() ; t++ )
                        {
                            int u = ans[t];
                            bool flag = true;
                            for ( int v = 1 ; v <= k ; v++ )
                                if ( pos[v][u] >= pos[v][x] ) 
                                    flag = false;
                            if ( flag )
                                dp[x] = max ( dp[x] , dp[u]+1 );
                        }
                        ans.push_back ( x );  
                        cnt[x]++;
                    }
                }
            int pp = 0;
            for ( int i = 1 ; i <= n ; i++ )
                pp = max ( pp , dp[i] );
            printf ( "%d
    "
    , pp ); } }

    좋은 웹페이지 즐겨찾기