PAT 甲級 A1045(動態規劃10ms解決)

題目連接

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章