LCIS - 每天一把CF - 20201117

2020-11-17

dp 记忆化搜索

10D 2800

题目

原题链接:https://codeforces.com/problemset/problem/10/D

在这里插入图片描述

思路

题目大意:求两个数列的最长公共上升子序列

思路:如果会最长公共子序列的话还是蛮简单的这道题

首先最长公共上升子序列一定是最长公共子序列的子集,所以我们其实再加一个条件-前面最长的子序列的末尾字母一定要小于当前字母即可。

最后注意一下即使当前ij位的字母相同 我也可以不选,例如这两个数列最后的1

2 3 4 5 6 1
2 3 5 6 1

如此,可解。

代码实现

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <string>
#include <queue>
using namespace std;

#define mes0(c) memset((c),0,sizeof(c))
#define mesi(c) memset((c),ifi,sizeof(c))
#define mes(c,n) memset((c),(n),sizeof(c))
#define fsios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define rep1(n) for (int i=1;i<=(n);i++)
#define rep2(n) for (int j=1;j<=(n);j++)
#define inp(a, n) for (int i = 1; i <= (n); i++) cin >> a[i];
#define ll long long
#define fi first
#define se second

const ll MAX = 505;
const int ifi = 0x3f3f3f3f;
const int mod = 1e9 + 7;

int n, m, mx;
int a[MAX], b[MAX];
int  dp[MAX][MAX];
string ans[MAX][MAX];

//int dfs1(int i, int j) {
//	if (i == 0 || j == 0)return 0;
//	if (dp[i][j] != -1)return dp[i][j];
//	if (a[i] == b[j]) {
//		return dp[i][j] = dfs1(i - 1, j - 1) + 1;
//	}
//	else {
//		return dp[i][j] = max(dfs1(i - 1, j), dfs1(i, j - 1));
//	}
//}

string numToStr(int x) {
	string s;
	s.clear();
	if (x == 0) s += char(x % 10 + '0');
	while (x) {
		s += char(x % 10 + '0');
		x /= 10;
	}
	reverse(s.begin(), s.end());
	return s;
}

int dfs(int i, int j) {
	if (i == 0 || j == 0)return 0;
	if (dp[i][j] != -1)return dp[i][j];
	
	dp[i][j] = 0;
	if (a[i] == b[j]) {
		dp[i][j] = 1;
		ans[i][j] = numToStr(a[i]) + ' ';
		for (int x = i - 1; x; x--) {
			for (int y = j - 1; y; y--) {
				if (a[x] == b[y] && a[x] < a[i])
					if (dfs(x, y) + 1 > dp[i][j])
					{
						dp[i][j] = dfs(x, y) + 1;
						ans[i][j] = ans[x][y] + numToStr(a[i]) + ' ';
					}
			}
		}
	}
	//即使字符相同 我也可以不选	
	mx = max(mx, dp[i][j]);
	dfs(i - 1, j); dfs(i, j - 1);
	return dp[i][j];
}

int main() {
	fsios;

	while (cin >> n)
	{
		mes0(a); mes0(b);
		mes(dp, -1); mx = 0;
		rep1(n) rep2(n) ans[i][j].clear();

		inp(a, n);
		cin >> m;
		inp(b, m);

		dfs(n, m);

		cout << mx << endl;

		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= m; j++)
				if (dp[i][j] == mx)
				{
					cout << ans[i][j] << endl;
					goto F;
				}

	F:;

	}
}
相关推荐
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:白松林 返回首页