Codeforces 463D. Gargari and Permutations【DP】

題目大意:

給出1~n的k個排列(2<=k<=5),要求其中的最長公共子序列。

做法:

算是不難的DP,dp[i]表示以i爲結尾的最長公共子序列的長度,由於每個數在一個排列中只可能出現一次,我們用一個二維數組pos[i][j]表示數字j在第i行出現在第幾個位置,再用一個數組cnt[i] 記錄i出現了多少次;當第i個數出現了k次之後,說明能夠以該數爲結尾構成公共子序列,那麼dp[i]=max(dp[j]+1),其中i,j滿足pos[u][i]>pos[u][j](1<=u<=k);當然,爲了節約時間,我們可以把之前已經計算過的dp[i]值的下標存到vector裏面,這樣只需要遍歷這個vector找出符合條件的數即可.

代碼:
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#define N 1010
using namespace std;
int pos[6][N],cnt[N],a[6][N],dp[N];
vector<int> q;
int main()
{
    int n,k,ans=0;
    scanf("%d%d",&n,&k);
    for(int i=0;i<k;i++)
        for(int j=0;j<n;j++)
            scanf("%d",&a[i][j]);
    for(int i=0;i<n;i++)
        for(int j=0;j<k;j++){
            int cur=a[j][i];
            pos[j][cur]=i;
            cnt[cur]++;
            if(cnt[cur]==k){
                if(q.size()==0) dp[cur]=1;
                else for(int kk=0;kk<q.size();kk++){
                        bool flag=false;
                        for(int l=0;l<k;l++)
                            if(pos[l][cur]<pos[l][q[kk]]) {flag=true;break;}
                        if(!flag) dp[cur]=max(dp[cur],dp[q[kk]]+1);
                        else dp[cur]=max(dp[cur],1);
                    }
                ans=max(ans,dp[cur]);
                q.push_back(a[j][i]);
            }
        }
    cout<<ans<<endl;
    return 0;
}


發佈了85 篇原創文章 · 獲贊 3 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章