POJ 2127 LCIS DP

http://poj.org/problem?id=2127

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cstdio>
#include <map>
#include <vector>
using namespace std;
const int N=5e2+20;
const int inf=2e8;
//题意:a,b两个数组,长度<=500,a[i],b[i]<=1e9,求出a,b最长公共递增子序列?
//设dp[i][j] a的前i个字符和b的前j个字符&&以b[j]结尾的LCIS长度
//a[i]!=b[j]: dp[i][j]=dp[i-1][j]
//a[i]==b[j]: dp[i][j]=max(dp[i-1][k]+1 ) ( 1<=k<j,b[k]<b[j]=a[i])  

int dp[N][N];//a的前i个字符和b的前j个字符&&以b[j]结尾的LCIS长度
int path[N][N];//LCIS 以b[j]结尾,记录此时决策
int n,m,a[N],b[N];
vector<int> res;
int main()
{
	while(cin>>n)
	{
		res.clear();
		int p,q;
		for(int i=1;i<=n;i++)
			cin>>a[i];
		cin>>m;
		for(int i=1;i<=m;i++)
			cin>>b[i];
		memset(dp,0,sizeof(dp));
		memset(path,0,sizeof(path));
		int ans=0,mj;
		for(int i=1;i<=n;i++)
		{
			int mx=0;
			for(int j=1;j<=m;j++)
			{

				dp[i][j]=dp[i-1][j];//a[i]!=b[j]
				path[i][j]=-1;
				if(b[j]<a[i]&&dp[i-1][j]>mx)
				{
					mx=dp[i-1][j];
					mj=j;
				}
				else if(a[i]==b[j])
				{
					dp[i][j]=mx+1;
					path[i][j]=mj;
				}
				if(ans<dp[i][j])
				{
					ans=dp[i][j];
					p=i,q=j;
				}
			}
		}
		cout<<ans<<endl;
		while(ans)
		{
			if(path[p][q]>-1)
			{
				ans--;
				res.push_back(b[q]);
				q=path[p][q];
			}
			p--;
		}
		for(int i=res.size()-1;i>=0;i--)
			printf("%d%c",res[i],i==0?‘\n‘:‘ ‘);
	}

	return 0;
}

  

时间: 2024-12-06 15:27:57

POJ 2127 LCIS DP的相关文章

poj 2127 lcis wa

#include<iostream> #include<cstdio> #include<stack> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int maxn = 505; const ll one = 1; const ll inf = one << 32; ll n1, n2, a[maxn],

POJ 2127 最长公共上升子序列

动态规划法: #include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #include <cstring> #inc

poj 3342(树形dp)

题意:在一个公司中要举办一个聚会,每一个员工有一个奉献值.为了和谐规定直接上下级不能一起出席.让你找出奉献值之和最大为多少. 思路:dp[v][1]表示当前结点选,能获得的最大奉献值,dp[v][0]表示当前节点不选能获得的最大奉献值.状态转移: dp[v][0] = max(dp[v][0], ∑max(dp[x][1], dp[x][0]))x为直接儿子 dp[v][1] = max(dp[v][1], ∑dp[x][0] + vex[v]) 最后答案是max(dp[root][0], dp

poj 2151 概率dp

//poj 2151 概率dp 1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "algorithm" 5 using namespace std; 6 double dp[33][33]; 7 int M, T, N; //problem, team, least 8 double p[1010][33]; 9 int mai

POJ 2250 Compromise (DP,最长公共子序列)

Compromise Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6440 Accepted: 2882 Special Judge Description In a few months the European Currency Union will become a reality. However, to join the club, the Maastricht criteria must be fulfille

poj 1947(树形dp)

题意:一棵树上问你最少切掉几条边使得能分割出一个结点数正好为k的子树. 思路:dp[i][j]表示以i为根切掉j个结点最少要几条边. dp[v][j] = min(dp[v][j], dp[v][j-k] + dp[x][k]); 代码如下: 1 dp[v][j] = min(dp[v][j], dp[v][j-k] + dp[x][k]); 2 } 3 } 4 } 5 } 6 } 7 return vex[v]; 8 } 9 10 int main() 11 { 12 // freopen("

POJ 2486 树形DP

有一颗苹果树,每个节点上面有很多苹果,从一个节点到另外一个可以到达的节点花费1步,求k步最多能吃到多少苹果,起始点为1,可以不回到起始点. 这是典型的回溯型树状dp. dp[i][j][0]代表以i为根节点的子树最多j步后回到i能吃到的最多的苹果, dp[i][j][1]代表以i为根节点的子树最多j步后不回到i节点最多能吃到的子树.那么状态转移就分三步了. (1)dp[i][j+2][0] = max(dp[i][j+2][0], dp[i][j-k][0]+dp[son][k][0]); (2

POJ 2411 插头DP

1 //插头DP,算是广义路径的吧. 2 /* 3 我是这样想的,定义填数的为0,未填的为1.然后,初始自然是(0,0).我还定义了整个棋盘的状态,不知是否多此一举. 4 这样,把轮廓线上的格子状态记录.当(I,J)上方的格子为空,必定要填一个竖的.当左边格子为空,当前可填一个横的,也可不填. 5 当左边格子不为空,当前格子必为空...AC. 6 */ 7 8 #include <iostream> 9 #include <cstdio> 10 using namespace st

poj 1458 动态规划DP

//  poj 1458  zoj 1733  最长公共子序列  DP #include <iostream>#include <string.h>#define N 1005using namespace std ;char  s1[N],s2[N];   int dp[N][N];int max(int a,int b)   {    return a>b ? a : b ;  }void f(int n,int m){   int i,j;    for (i=0; i