題目意思: 給定一個正確的編號序列,然後對輸入的每一組序列找最長公共子序列
解題思路: 動態規劃
1:題目給定的n個數並不是表示當前位置的值就是Ai,而是表示第i個數放在第Ai個位置,看樣列4 2 3 1,說明1放在第四位,2放在第二位,3放在第三位,4放在第一位。
2:題目就是要求出最長的公共子序列,由於題目的n最大才20,那麼我們可以直接去枚舉。假設現在枚舉到Ai這個數,那麼我們就求i之前的所以數能夠和Ai構成連續的序列最大值dp[i],然後判斷能否更新最大值(max_point < dp[i]),最後輸出這個最大值即可。
代碼:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
using namespace std;
#define MAXN 25
int n;
int correct[25];//存儲正確的順序
int order[MAXN];//要求的順序
int dp[MAXN];
void solve(){
int max_point = 0;
int pos_i , pos_j;//記錄在correct數組中的位置
dp[0] = 1;
for(int i = 1 ; i < n ; i++){
dp[i] = 1;//初始化爲1
for(int j = i-1 ; j >= 0 ;j--){//搜索i之前的數
for(int k = 0 ; k < n ; k++){//去correct數組中找到order[i] 和order[j]的位置
if(correct[k] == order[i]) pos_i = k;
if(correct[k] == order[j]) pos_j = k;
}
if(pos_i > pos_j){//如果i在j後面說明是連續的,求dp[i]
if(dp[j]+1 > dp[i]) dp[i] = dp[j]+1;
}
}
if(max_point < dp[i]) max_point = dp[i];//更新max_point
}
printf("%d\n" , max_point);
}
int main(){
//freopen("input.txt" , "r" , stdin);
int m;
scanf("%d" , &n);
for(int i = 1 ; i <= n ; i++){
scanf("%d" , &m) ; correct[m-1] = i;//求出correct數組
}
while(scanf("%d" , &m) != EOF){
order[m-1] = 1;
for(int j = 2 ; j <= n ; j++) {
scanf("%d" , &m) ; order[m-1] = j;//求出order數組
}
solve();
}
return 0;
}