POJ 2127: Greatest Common Increasing Subsequence (最大公共上升子序列)

题目来源: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
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值