# Dynamic Programming# LCS# String

a133 - 10066 - The Twin Towers

🔗 前往 ZeroJudge 原題

題目描述

題目要求計算兩個塔(由磁磚組成)之間最長共同子序列的長度,代表可以保留的最大磁磚數,使得兩座塔的形狀大小相同,且維持原始順序。

解題思路

本題可以轉化為求兩個序列的最長公共子序列 (Longest Common Subsequence, LCS) 問題。塔的磁磚半徑序列可以視為兩個字串,LCS 的長度即為兩座塔可以保留的最大磁磚數。 使用動態規劃 (Dynamic Programming) 解決 LCS 問題。定義 len[i][j] 為第一座塔的前 i 個磁磚和第二座塔的前 j 個磁磚的最長公共子序列的長度。

  • 如果 c[i] == d[j],則 len[i][j] = len[i-1][j-1] + 1
  • 否則,len[i][j] = max(len[i-1][j], len[i][j-1])。 最終結果為 len[a][b],其中 ab 分別是兩座塔的磁磚數。

複雜度分析

  • 時間複雜度: O(n*m),其中 n 和 m 分別是兩座塔的磁磚數。因為需要遍歷一個 n x m 的矩陣。
  • 空間複雜度: O(n*m),因為需要一個 n x m 的矩陣來儲存中間結果。

程式碼

#include <iostream>
using namespace std;
int main(){
	int a,b,ca=0;
	while(cin >> a >> b){
		if(a==0&&b==0)break;
		++ca;
		int c[a+1],d[b+1],li=0;
		int len[a+1][b+1];
		for(int i=1;i<=a;++i)
			cin >> c[i];
		for(int i=1;i<=b;++i)
			cin >> d[i];
		for (int i=0; i<=a; ++i)
			len[i][0] = 0;
    	for (int i=0; i<=b; ++i) 
			len[0][i] = 0;
		for(int i=1;i<=a;++i){
			for(int j=1;j<=b;++j){
				if(c[i]==d[j])
					len[i][j]=len[i-1][j-1]+1;	
				else
					len[i][j]=max(len[i-1][j],len[i][j-1]);
			}
		}
		cout << "Twin Towers #"<< ca  << "\nNumber of Tiles : " << len[a][b] << "\n\n";
	}
}

Discussion