Once upon a time, in an ancient Empire, there were two towers of dissimilar shapes in two different
cities. The towers were built by putting circular tiles one upon another. Each of the tiles was of the
same height and had integral radius. It is no wonder that though the two towers were of dissimilar
shape, they had many tiles in common.
However, more than thousand years after they were built, the Emperor ordered his architects to
remove some of the tiles from the two towers so that they have exactly the same shape and size, and
at the same time remain as high as possible. The order of the tiles in the new towers must remain the
same as they were in the original towers. The Emperor thought that, in this way the two towers might
be able to stand as the symbol of harmony and equality between the two cities. He decided to name
them the Twin Towers.
Now, about two thousand years later, you are challenged with an even simpler problem: given the
descriptions of two dissimilar towers you are asked only to find out the number of tiles in the highest
twin towers that can be built from them.
Input
The input file consists of several data blocks. Each data block describes a pair of towers. The first line
of a data block contains two integers N1 and N2 (1 ≤ N1, N2 ≤ 100) indicating the number of tiles
respectively in the two towers. The next line contains N1 positive integers giving the radii of the tiles
(from top to bottom) in the first tower. Then follows another line containing N2 integers giving the
radii of the tiles (from top to bottom) in the second tower.
The input file terminates with two zeros for N1 and N2.
Output
For each pair of towers in the input first output the twin tower number followed by the number of tiles
(in one tower) in the highest possible twin towers that can be built from them. Print a blank line after
the output of each data set.
Sample Input
7 6
20 15 10 15 25 20 15
15 25 10 20 15 20
8 9
10 20 20 10 20 10 20 10
20 10 20 10 10 20 10 10 20
0 0
Sample Output
cities. The towers were built by putting circular tiles one upon another. Each of the tiles was of the
same height and had integral radius. It is no wonder that though the two towers were of dissimilar
shape, they had many tiles in common.
However, more than thousand years after they were built, the Emperor ordered his architects to
remove some of the tiles from the two towers so that they have exactly the same shape and size, and
at the same time remain as high as possible. The order of the tiles in the new towers must remain the
same as they were in the original towers. The Emperor thought that, in this way the two towers might
be able to stand as the symbol of harmony and equality between the two cities. He decided to name
them the Twin Towers.
Now, about two thousand years later, you are challenged with an even simpler problem: given the
descriptions of two dissimilar towers you are asked only to find out the number of tiles in the highest
twin towers that can be built from them.
Input
The input file consists of several data blocks. Each data block describes a pair of towers. The first line
of a data block contains two integers N1 and N2 (1 ≤ N1, N2 ≤ 100) indicating the number of tiles
respectively in the two towers. The next line contains N1 positive integers giving the radii of the tiles
(from top to bottom) in the first tower. Then follows another line containing N2 integers giving the
radii of the tiles (from top to bottom) in the second tower.
The input file terminates with two zeros for N1 and N2.
Output
For each pair of towers in the input first output the twin tower number followed by the number of tiles
(in one tower) in the highest possible twin towers that can be built from them. Print a blank line after
the output of each data set.
Sample Input
7 6
20 15 10 15 25 20 15
15 25 10 20 15 20
8 9
10 20 20 10 20 10 20 10
20 10 20 10 10 20 10 10 20
0 0
Sample Output
Twin Towers #1
Number of Tiles : 4
Number of Tiles : 6
题意分析:
求两个字符数组的最大公共子序列,每组输出之间空一行,若输入为0 0时,结束。
简单DP
状态转移图如下(找学长要的):
状态转移方程
/ 0 i=0,j=0
c[i][j]=-- c[i-1][j-1]+1 i,j>0,xi=yi
\ max(c[i-1][j],c[i][j-1]) i,j>0,xi!=yi
3种情况,3种走法,每次都是取最大
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<ctype.h> #include<stdlib.h> #include<string> #include<algorithm> #include<vector> #include<set> #include<map> #include<list> #include<queue> #include<stack> #include<iomanip> #include<numeric> //#include <istream> //基本输入流 //#include <ostream> //基本输出流 //#include <sstream> //基于字符串的流 //#include <utility> //STL 通用模板类 //#include <complex.h> //复数处理 //#include <fenv.h> //浮点环境 //#include <inttypes.h> //整数格式转换 //#include <stdbool.h> //布尔环境 //#include <stdint.h> //整型环境 //#include <tgmath.h> //通用类型数学宏 #define L(a,b,c) for(int a = b;a >= c;a --) #define M(a,b,c) for(int a = b;a <= c;a ++) #define N(a,b) memset(a,b,sizeof(a)); #define MAXX(a,b) ((a)>(b)?a:b) #define MINN(a,b) ((a)<(b)?a:b) const int MAX=1<<30; const int MIN=-MAX; using namespace std; int a[111],b[111],dp[111][111],c[111][111]; int n,m; int LCS() { int i,j; for(i=1; i<=n; i++) for(j=1; j<=m; j++) { if(a[i]==b[j]) c[i][j]=c[i-1][j-1]+1; else if(c[i-1][j]>=c[i][j-1]) c[i][j]=c[i-1][j]; else c[i][j]=c[i][j-1]; } return c[n][m]; //返回最长公共子序列的长度 } int main() { int num=0; while(cin>>n>>m,n&&m) { M(i,1,n) cin>>a[i]; M(i,1,m) cin>>b[i]; printf("Twin Towers #%d\nNumber of Tiles : %d\n",++num,LCS()); printf("\n"); } return 0; }
当题目要求输出最长公共子序列时,怎么搞??
别急,代码如下:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<ctype.h>
#include<stdlib.h>
#include<string>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<iomanip>
#include<numeric>
//#include <istream> //基本输入流
//#include <ostream> //基本输出流
//#include <sstream> //基于字符串的流
//#include <utility> //STL 通用模板类
//#include <complex.h> //复数处理
//#include <fenv.h> //浮点环境
//#include <inttypes.h> //整数格式转换
//#include <stdbool.h> //布尔环境
//#include <stdint.h> //整型环境
//#include <tgmath.h> //通用类型数学宏
#define L(a,b,c) for(int a = b;a >= c;a --)
#define M(a,b,c) for(int a = b;a <= c;a ++)
#define N(a,b) memset(a,b,sizeof(a));
#define MAXX(a,b) ((a)>(b)?a:b)
#define MINN(a,b) ((a)<(b)?a:b)
const int MAX=1<<30;
const int MIN=-MAX;
using namespace std;
int a[111],b[111],dp[111][111],c[111][111];
int n,m;
int LCS()
{
int i,j;
for(i=1; i<=n; i++) ///同下一个for语句,都是用来控制边界
c[i][0]=0;
for(i=1; i<=m; i++)
c[0][i]=0;
for(i=1; i<=n; i++) ///查找最大公共子序列,并对求出最大公共子序列的步骤用b数组进行标记
for(j=1; j<=m; j++)
{
if(a[i]==b[j])
{
c[i][j]=c[i-1][j-1]+1;
dp[i][j]=1; ///输出时用到
}
else if(c[i-1][j]>=c[i][j-1])
{
c[i][j]=c[i-1][j];
dp[i][j]=2; ///输出时用到
}
else
{
c[i][j]=c[i][j-1];
dp[i][j]=3; ///输出时用到
}
}
return c[n][m];
}
void LCS_print(int x,int y,int aa[]) ///打印最长公共子序列
{
if(x==0||y==0) ///任意为0时终止
return;
if(dp[x][y]==1)
{
LCS_print(x-1,y-1,aa);
printf("%d ",aa[x]); ///输出最长公共子序列
}
else if(dp[x][y]==2)
LCS_print(x-1,y,aa);
else
LCS_print(x,y-1,aa);
}
int main()
{
int num=0;
while(cin>>n>>m,n&&m)
{
M(i,1,n) ///输入,下同上
cin>>a[i];
M(i,1,m)
cin>>b[i];
printf("Twin Towers #%d\nNumber of Tiles : %d\n",++num,LCS()); ///输出第几次和最长公共子序列的长度
printf("\n");
LCS_print(n,m,a); ///打印
printf("\n");
}
return 0;
}