您的位置:首页 > 其它

线性DP LCIS(最长公共上升子序列)CODE(VS)

2018-03-31 15:59 316 查看

2185 最长公共上升子序列

 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 钻石 Diamond题解题目描述 Description熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目。小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们要研究最长公共上升子序列了。
小沐沐说,对于两个串A,B,如果它们都包含一段位置不一定连续的数字,且数字是严格递增的,那么称这一段数字是两个串的公共上升子串,而所有的公共上升子串中最长的就是最长公共上升子串了。
奶牛半懂不懂,小沐沐要你来告诉奶牛什么是最长公共上升子串。不过,只要告诉奶牛它的长度就可以了。输入描述 Input Description第一行N,表示A,B的长度。
第二行,串A。
第三行,串B。输出描述 Output Description输出长度。样例输入 Sample Input4
2 2 1 3
2 1 2 3样例输出 Sample Output2数据范围及提示 Data Size & Hint1<=N<=3000,A,B中的数字不超过maxlongint

没办法解决这么大的空白

F[i,j]表示A1~Ai与B1~Bi可以构成的以Bj为结尾的LCIS的长度。

当Ai不等于Bj时,有F[i,j] = F[i-1, j]

当Ai等于Bj时,有F[i,j] = max{F[i-1,k]}+1(0=<k<j,Bk<Bj) = max{F[i-1,k]}+1(0=<k<j,Bk<Ai)
最后将j也循环就好了
递归做法
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int f(int * a, int * b, int la, int lb){
if(la == 0 || lb == 0) return 0;
if(a[la] == b[lb] ){
int re = 0;
for(int i = 0; i < lb; i++){
if(b[i] < b[lb]){
re = max(re, f(a, b, la-1, i) + 1);
}
}
return re;
}
else{
return f(a, b, la-1, lb);
}
}

int map[3001];
int main(){
freopen("in.txt", "r", stdin);
int a[3001];
int b[3001];
memset(map, 0, sizeof(map));
int n;
cin >> n;
for (int i = 1; i <= n; i++){
cin >> a[i];
}
for (int i = 1; i <= n; i++){
cin >> b[i];
}
int re = 0;
for(int i = 1; i <= n; i++){
re = max(re, f(a, b, n, i));
}
cout << re << endl;
}会超时(TLE)
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int map[3001][3001];
int map1[3001];
int map2[3001];
// map[i][j]表示以j结尾的串的最长上升公共子序列的长度
// i, j 的每个状态都是有用的吗?
//map[i][j]肯定是小于等于j的
//当mpa[i][j] == j的时候,i + 1, i + 2,...,n都是没有用的
int main(){
freopen("in.txt", "r", stdin);
int a[3001];
int b[3001];
memset(map, 0, sizeof(map));
int n;
cin >> n;
for (int i = 1; i <= n; i++){
cin >> a[i];
}
for (int i = 1; i <= n; i++){
cin >> b[i];
}
map1[0] = 0; //为什么要让map[0][0]  = 0;
for (int i = 1; i <= n; i++){   //i 从当前第一个有效数字起,到最后一个有效数字为止
for (int j = 1; j <= n; j++){ //j 从当前第一个有效数字起,到最后一个有效数字为止
map[i][j] = map[i - 1][j];
if (a[i] == b[j]){ //当a[i] == b[j]的时候,我们能够确认map[i][j]表示的
//最长公共上升子序列中有a[i](b[j])的位置
//map[i][j] 可以由 (map[i-1][j-1], map[i-1][j-2], ... , map[i-1][1])中的最大值
//+1得出 , 因为你不能保证b[s](1=<s<=j-1)一定在最长公共上升子序列里面
for (int k = 0; k < j; k++){
if (a[k] < b[j]){
map[i][j] = max(map[i][k] + 1, map[i][j]);
}
}
}
}
}
//	for (int i = 1; i <= n; i++){
//		for (int j = 1; j <= n; j++){
//			cout << map[i][j] << " ";
//		}
//		cout << endl;
//	}
int re = 0;
for (int i = 1; i <= n; i++){ //我们要找的是
re = max(re, map2[i]);
}
cout << re << endl;
}
内存超限(Memory limit exceeded)

改进版:

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int map1[3001];
int map2[3001];
// map1 表示上一个结果集合
// map2 表示现在得到的结果集合
int main(){
freopen("in.txt", "r", stdin);
int a[3001];
int b[3001];
memset(map, 0, sizeof(map));
int n;
cin >> n;
for (int i = 1; i <= n; i++){
cin >> a[i];
}
for (int i = 1; i <= n; i++){
cin >> b[i];
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
memcpy(map2, map1, sizeof(map1));
if(a[i] == b[j]){
for(int k = 0; k < j; k++){
//k 一定要从0开始,不然a[1],b[1],如果相等,那么得不到结果集合中的1
if(b[k] < b[j]){
map2[j] = max(map2[k] + 1, map2[j]);
}
}
}
memcpy(map1, map2, sizeof(map1));
}
}

int re = 0;
for (int i = 1; i <= n; i++){ //我们要找的是最大的
re = max(re, map2[i]);
}
cout << re << endl;
}部分时间超限(Time limit exceeded)
AC版#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int map2[3001];
int main(){
freopen("in.txt", "r", stdin);
int a[3001];
int b[3001];
memset(map, 0, sizeof(map));
int n;
cin >> n;
for (int i = 1; i <= n; i++){
cin >> a[i];
}
for (int i = 1; i <= n; i++){
cin >> b[i];
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(a[i] == b[j]){
for(int k = 0; k < j; k++){
if(b[k] < b[j]){
map2[j] = max(map2[k] + 1, map2[j]);
//只用一个数组存储结果集合
}
}
}
}
}
int re = 0;
for (int i = 1; i <= n; i++){ //我们要找的是
re = max(re, map2[i]);
}
cout << re << endl;
}AC简化版
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int map[3001];
int main(){
freopen("in.txt", "r", stdin);
int a[3001];
int b[3001];
memset(map, 0, sizeof(map));
int n;
cin >> n;
for (int i = 1; i <= n; i++){
cin >> a[i];
}
for (int i = 1; i <= n; i++){
cin >> b[i];
}

for(int i = 1; i <= n; i++){
int val = 0;
for(int j = 1; j <= n; j++){
if(a[i] == b[j]) map[j] = val + 1;
if(b[j] < a[i]) val = max(val, map[j]);
}
}
int re = 0;
for (int i = 1; i <= n; i++){ //我们要找的是
re = max(re, map[i]);
}
cout << re << endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: