題目連接
1045 Favorite Color Stripe (30分)
題目大意
給定一個Eva喜歡的顏色序列和一個總的顏色序列,從總的顏色序列中找出按Eva喜歡的顏色序列順序出現的最長子序列。有點繞,結合樣例來說明什麼意思。假設Eva喜歡的顏色序列爲 {2 3 1 5 6}
,總的顏色序列爲{2 2 4 1 5 5 6 3 1 1 5 6}
.那麼需要從總的顏色序列中找出符合題意的序列有 {2 2 1 1 1 5 6}, {2 2 1 5 5 5 6}, {2 2 1 5 5 6 6}, {2 2 3 1 1 5 6}.
其中第一個序列按照2 1 5 6
的順序出現,滿足。
第二,三個序列按照 2 1 5 6
的順序出現,滿足。
第四個序列按照2 3 1 5 6
的順序出現,滿足。
思路
用動態規劃實現即可,dp[c]表示以顏色c結尾的序列長度,設dp[j]表示以顏色j結尾的序列長度,那麼狀態轉移方程可以表示爲:
dp[c] = max(dp[j]+1,dp[c]);
爲了保證dp[j]表示的是dp[c]更新之前的長度,這裏設置了temp來表示dp[c]未更新前的最長序列長度,所以狀態轉移方程爲:
dp[c] = max(temp[j]+1,dp[c]);
另外,Eva喜歡的顏色的出現順序,可以用一個數組w來表示。由於總的顏色序列中不一定含有Eva所喜歡的顏色,所以在執行狀態轉移方程前,需要簡單地判斷一下。所以就很容易地寫出了下面的代碼。
總的來說,程序的時間複雜度爲O(nm),其中m爲顏色的總數(給的最大爲200)。
AC代碼
#include<iostream>
#define maxn 10010
#define maxc 205
using namespace std;
int n, m, l, ans = 0;
int w[maxc];
int dp[maxc],temp[maxc];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int c;
cin >> n >> m; //n沒什麼卵用
for (int i = 1; i <= m; i++) {
cin >> c;
w[c] = i;
}
cin >> l;
for (int i = 0; i < l; i++) {
cin >> c;
if (!w[c]) continue;
for (int j = 0; j < maxc; j++) {
if (!w[j] ||w[j] > w[c]) continue;
dp[c] = max(dp[c], temp[j] + 1);
}
dp[c] = max(1, dp[c]);
ans = max(dp[c], ans);
for (int j = 0; j < maxc; j++) { //temp記錄了上次的dp
temp[j] = dp[j];
}
}
cout << ans;
return 0;
}