题目来源:http://poj.org/problem?id=2127
Greatest Common Increasing Subsequence
Time Limit: 10000MS | Memory Limit: 65536K |
Total Submissions: 12704 | Accepted: 3308 |
Case Time Limit: 2000MS | Special Judge |
Description
You are given two sequences of integer numbers.Write a program to determine their common increasing subsequence of maximalpossible length.
Sequence S1 , S2 , . . . , SN oflength N is called an increasing subsequence of a sequence A1 ,A2 , . . . , AM of length M if there exist 1<= i1 < i2 < . . . < iN <=M such that Sj = Aij for all 1 <= j <= N, and Sj < Sj+1 for all 1 <= j < N .
Input
Each sequence is described with M --- its length(1 <= M <= 500) and M integer numbers Ai (-231 <=Ai < 231 ) --- the sequence itself.
Output
On the first line of the output file print L ---the length of the greatest common increasing subsequence of both sequences. Onthe second line print the subsequence itself. If there are several possibleanswers, output any of them.
Sample Input
5
1 4 2 5 -12
4
-12 1 2 4
SampleOutput
2
1 4
Source
Northeastern Europe 2003,Northern Subregion
-----------------------------------------------------
解题思路
动态规划
dp[i][j]: a中前i个数和b中前j个数且以b[j]为结尾的最长公共上升子序列长度
dp[i][j] =dp[i-1][j], a[i]!=b[j]
= max(dp[i-1][k]+1), a[i]==b[j],b[j]>b[k], 0<=k<j
结果为dp[n-1][j](0<=j<n)中的最大值
采用一维优化,dp[j]: dp[i][j]
/********** 太难想到啦 **************************/
-----------------------------------------------------
代码
代码实现参考神犇(shenben)的博客园
// dp[i][j]: a中前i个数和b中前j个数且以b[j]为结尾的最长公共上升子序列长度
// dp[i][j] = dp[i-1][j], a[i]!=b[j]
// = max(dp[i-1][k]+1), a[i]==b[j], b[j]>b[k], 0<=k<j
// 结果为dp[n-1][j](0<=j<n)中的最大值
// 采用一维优化
// dp[j]: dp[i][j]
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;
struct DP{
int len; // 公共子列长度
vector<int> v; // 公共子列, "="可以把整个vector拷贝过去
};
int m,n;
int M[505] = {};
int N[505] = {};
DP dp[505] = {};
int main()
{
#ifndef ONLINE_JUDGE
ifstream fin("0206_2000.txt");
int i,j,k;
fin >> m;
for (i=0; i<m; i++)
{
fin >> M[i];
}
fin >> n;
for (i=0; i<n; i++)
{
fin >> N[i];
}
fin.close();
bool has_larger = false;
DP current;
for (i=0; i<m; i++)
{
current.len = 0;
current.v.clear();
for (j=0; j<n; j++)
{
if (M[i]>N[j] && dp[j].len>current.len)
{
current = dp[j];
}
else if (M[i]==N[j])
{
dp[j] = current;
dp[j].len++;
dp[j].v.push_back(N[j]);
}
}
}
int mymax = 0;
int myindex = 0;
for (i=0; i<n; i++)
{
if (dp[i].len>mymax)
{
mymax = dp[i].len;
myindex = i;
}
}
cout << dp[myindex].len << endl;
for (vector<int>::iterator it = dp[myindex].v.begin(); it!=dp[myindex].v.end(); it++)
{
cout << (*it) << " " ;
}
return 0;
#endif
#ifdef ONLINE_JUDGE
int i,j,k;
cin >> m;
for (i=0; i<m; i++)
{
cin >> M[i];
}
cin >> n;
for (i=0; i<n; i++)
{
cin >> N[i];
}
bool has_larger = false;
DP current;
for (i=0; i<m; i++)
{
current.len = 0;
current.v.clear();
for (j=0; j<n; j++)
{
if (M[i]>N[j] && dp[j].len>current.len)
{
current = dp[j];
}
else if (M[i]==N[j])
{
dp[j] = current;
dp[j].len++;
dp[j].v.push_back(N[j]);
}
}
}
int mymax = 0;
int myindex = 0;
for (i=0; i<n; i++)
{
if (dp[i].len>mymax)
{
mymax = dp[i].len;
myindex = i;
}
}
cout << dp[myindex].len << endl;
for (vector<int>::iterator it = dp[myindex].v.begin(); it!=dp[myindex].v.end(); it++)
{
cout << (*it) << " " ;
}
return 0;
#endif
}