HDU 1423 && ZOJ 2432 (LCIS模板)
2017-08-29 00:13
323 查看
定义状态
F[i][j]表示以a串的前i个整数与b串的前j个整数且以b[j]为结尾构成的LCIS的长度。
状态转移方程:
①F[i][j] = F[i-1][j] (a[i] != b[j])
②F[i][j] = max(F[i-1][k]+1) (1 <= k <= j-1 && b[j] > b[k])
现在我们来说为什么会是这样的状态转移方程呢?
对于①,因为F[i][j]是以b[j]为结尾的LCIS,如果F[i][j]>0那么就说明a[1]..a[i]中必然有一个整数a[k]等于b[j],因为a[k]!=a[i],那么a[i]对F[i][j]没有贡献,于是我们不考虑它照样能得出F[i][j]的最优值。所以在a[i]!=b[j]的情况下必然有F[i][j]=F[i-1][j]。
对于②,前提是a[i] == b[j],我们需要去找一个最长的且能让b[j]接在其末尾的LCIS。之前最长的LCIS在哪呢?首先我们要去找的F数组的第一维必然是i-1。因为i已经拿去和b[j]配对去了,不能用了。并且也不能是i-2,因为i-1必然比i-2更优。第二维呢?那就需要枚举b[1]...b[j-1]了,因为你不知道这里面哪个最长且哪个小于b[j]。这里还有一个问题,可不可能不配对呢?也就是在a[i]==b[j]的情况下,需不需要考虑F[i][j]=F[i-1][j]的决策呢?答案是不需要。因为如果b[j]不和a[i]配对,那就是和之前的a[1]...a[j-1]配对(假设F[i-1][j]>0,等于0不考虑),这样必然没有和a[i]配对优越。(为什么必然呢?因为b[j]和a[i]配对之后的转移是max(F[i-1][k])+1,而和之前的i`配对则是max(F[i`-1][k])+1。
以上的代码的时间复杂度是O(n^3),那我们怎么去优化呢?通过思考发现,第三层循环找最大值是否可以优化呢?我们能否直接把枚举最大的f[i-1][k]值直接算出来呢?假设存在这么一个序列a[i] == b[j],我们继续看状态转移方程②,会发现b[j] > b[k],即当a[i] == b[j]时,可以推出a[i]
> b[k],那么有了这个表达式我们可以做什么呢?可以发现,我们可以维护一个MAX值来储存最大的f[i-1][k]值。即只要有a[i] > a[j]的地方,那么我们就可以更新最大值,所以,当a[i] == b[j]的时候,f[i][j] = MAX+1,即可
可以发现,其实上面的代码有些地方与0/1背包很相似,即每次用到的只是上一层循环用到的值,即f[i-1][j],那么我们可以像优化0/1背包问题利用滚动数组来优化空间。如果是求最长公共下降子序列呢?很明显嘛,把状态定义改动一下,即f[i][j]表示以a串的前i个整数与b串的前j个整数且以b[j]为结尾构成的LCDS的长度,具体实现的时候只要把a[i] > b[j]改为a[i] < b[j]就可以啦。
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 8249 Accepted Submission(s): 2666
Problem Description
This is a problem from ZOJ 2432.To make it easyer,you just need output the length of the subsequence.
Input
Each sequence is described with M - its length (1 <= M <= 500) and M integer numbers Ai (-2^31 <= Ai < 2^31) - the sequence itself.
Output
output print L - the length of the greatest common increasing subsequence of both sequences.
Sample Input
1
5
1 4 2 5 -12
4
-12 1 2 4
Sample Output
2
Source
ACM暑期集训队练习赛(二)
Recommend
lcy
Greatest Common Increasing Subsequence
Time Limit: 2 Seconds Memory Limit: 65536 KB Special Judge
You are given two sequences of integer numbers. Write a program to determine their common increasing subsequence of maximal
possible length.
Sequence S1, S2, ..., SN of length 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 (-2^31 <= Ai < 2^31) - the sequence itself.
Output
On the first line of the output print L - the length of the greatest common increasing subsequence of both sequences. On the second line print the subsequence itself. If there are several
possible answers, output any of them.
This problem contains multiple test cases!
The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank
line between input blocks.
The output format consists of N output blocks. There is a blank line between output blocks.
Sample Input
1
5
1 4 2 5 -12
4
-12 1 2 4
Sample Output
2
1 4
Source: Northeastern Europe 2003, Northern Subregion
Submit Status
记录路径
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 505;
int n, m, t, a[maxn], b[maxn], dp[maxn][maxn], pathx[maxn][maxn], pathy[maxn][maxn], cur, ans;
void Printf(int x, int y)
{
if(dp[x][y] == 0)
return;
if(pathx[x][y] != -1 && pathy[x][y] != -1)
{
int tx = pathx[x][y];
int ty = pathy[x][y];
Printf(tx, ty);
if(dp[x][y] != dp[tx][ty] && y != 0)
{
cur++;
if(cur < ans)
printf("%d ", b[y]);
else
printf("%d\n", b[y]);
}
}
}
int main()
{
cin >> t;
while(t--)
{
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
scanf("%d", &m);
for(int i = 1; i <= m; i++) scanf("%d", &b[i]);
memset(dp, 0, sizeof(dp));
memset(pathx, -1, sizeof(pathx));
memset(pathy, -1, sizeof(pathy));
int tmpx = 0, tmpy = 0;
for(int i = 1; i <= n; i++)
{
tmpx = 0, tmpy = 0;
int maxx = 0;
for(int j = 1; j <= m; j++)
{
dp[i][j] = dp[i-1][j];
pathx[i][j] = i-1;
pathy[i][j] = j;
if(a[i] > b[j] && maxx < dp[i-1][j]) maxx = dp[i-1][j], tmpx = i-1, tmpy = j;
if(a[i] == b[j]) dp[i][j] = maxx+1, pathx[i][j] = tmpx, pathy[i][j] = tmpy;
}
}
ans = 0;
int flag = -1;
for(int i = 1; i <= m; i++)
{
if(ans < dp
[i])
{
flag = i;
ans = dp
[i];
}
}
printf("%d\n", ans);
tmpx = n, tmpy = flag;
cur = 0;
if(tmpy > 0)
Printf(tmpx, tmpy);
if(t != 0)
puts("");
}
return 0;
}
Greatest Common Increasing Subsequence
Time Limit: 2 Seconds Memory Limit: 65536 KB Special Judge
You are given two sequences of integer numbers. Write a program to determine their common increasing subsequence of maximal
possible length.
Sequence S1, S2, ..., SN of length 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 (-2^31 <= Ai < 2^31) - the sequence itself.
Output
On the first line of the output print L - the length of the greatest common increasing subsequence of both sequences. On the second line print the subsequence itself. If there are several
possible answers, output any of them.
This problem contains multiple test cases!
The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank
line between input blocks.
The output format consists of N output blocks. There is a blank line between output blocks.
Sample Input
1
5
1 4 2 5 -12
4
-12 1 2 4
Sample Output
2
1 4
Source: Northeastern Europe 2003, Northern Subregion
Submit Status
F[i][j]表示以a串的前i个整数与b串的前j个整数且以b[j]为结尾构成的LCIS的长度。
状态转移方程:
①F[i][j] = F[i-1][j] (a[i] != b[j])
②F[i][j] = max(F[i-1][k]+1) (1 <= k <= j-1 && b[j] > b[k])
现在我们来说为什么会是这样的状态转移方程呢?
对于①,因为F[i][j]是以b[j]为结尾的LCIS,如果F[i][j]>0那么就说明a[1]..a[i]中必然有一个整数a[k]等于b[j],因为a[k]!=a[i],那么a[i]对F[i][j]没有贡献,于是我们不考虑它照样能得出F[i][j]的最优值。所以在a[i]!=b[j]的情况下必然有F[i][j]=F[i-1][j]。
对于②,前提是a[i] == b[j],我们需要去找一个最长的且能让b[j]接在其末尾的LCIS。之前最长的LCIS在哪呢?首先我们要去找的F数组的第一维必然是i-1。因为i已经拿去和b[j]配对去了,不能用了。并且也不能是i-2,因为i-1必然比i-2更优。第二维呢?那就需要枚举b[1]...b[j-1]了,因为你不知道这里面哪个最长且哪个小于b[j]。这里还有一个问题,可不可能不配对呢?也就是在a[i]==b[j]的情况下,需不需要考虑F[i][j]=F[i-1][j]的决策呢?答案是不需要。因为如果b[j]不和a[i]配对,那就是和之前的a[1]...a[j-1]配对(假设F[i-1][j]>0,等于0不考虑),这样必然没有和a[i]配对优越。(为什么必然呢?因为b[j]和a[i]配对之后的转移是max(F[i-1][k])+1,而和之前的i`配对则是max(F[i`-1][k])+1。
以上的代码的时间复杂度是O(n^3),那我们怎么去优化呢?通过思考发现,第三层循环找最大值是否可以优化呢?我们能否直接把枚举最大的f[i-1][k]值直接算出来呢?假设存在这么一个序列a[i] == b[j],我们继续看状态转移方程②,会发现b[j] > b[k],即当a[i] == b[j]时,可以推出a[i]
> b[k],那么有了这个表达式我们可以做什么呢?可以发现,我们可以维护一个MAX值来储存最大的f[i-1][k]值。即只要有a[i] > a[j]的地方,那么我们就可以更新最大值,所以,当a[i] == b[j]的时候,f[i][j] = MAX+1,即可
可以发现,其实上面的代码有些地方与0/1背包很相似,即每次用到的只是上一层循环用到的值,即f[i-1][j],那么我们可以像优化0/1背包问题利用滚动数组来优化空间。如果是求最长公共下降子序列呢?很明显嘛,把状态定义改动一下,即f[i][j]表示以a串的前i个整数与b串的前j个整数且以b[j]为结尾构成的LCDS的长度,具体实现的时候只要把a[i] > b[j]改为a[i] < b[j]就可以啦。
Greatest Common Increasing Subsequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 8249 Accepted Submission(s): 2666
Problem Description
This is a problem from ZOJ 2432.To make it easyer,you just need output the length of the subsequence.
Input
Each sequence is described with M - its length (1 <= M <= 500) and M integer numbers Ai (-2^31 <= Ai < 2^31) - the sequence itself.
Output
output print L - the length of the greatest common increasing subsequence of both sequences.
Sample Input
1
5
1 4 2 5 -12
4
-12 1 2 4
Sample Output
2
Source
ACM暑期集训队练习赛(二)
Recommend
lcy
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int maxn = 5e2 + 5; int dp[maxn], a[maxn], b[maxn], n, m; int main() { int t; cin >> t; while(t--) { memset(dp, 0, sizeof(dp)); scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); scanf("%d", &m); for(int i = 1; i <= m; i++) scanf("%d", &b[i]); for(int i = 1; i <= n; i++) { int maxx = 0; for(int j = 1; j <= m; j++) { if(a[i] > b[j]) maxx = max(maxx, dp[j]); if(a[i] == b[j]) dp[j] = maxx + 1; } } int ans = 0; for(int i = 1; i <= m; i++) ans = max(ans, dp[i]); if(t != 0) printf("%d\n\n", ans); else printf("%d\n", ans); } return 0; }
Greatest Common Increasing Subsequence
Time Limit: 2 Seconds Memory Limit: 65536 KB Special Judge
You are given two sequences of integer numbers. Write a program to determine their common increasing subsequence of maximal
possible length.
Sequence S1, S2, ..., SN of length 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 (-2^31 <= Ai < 2^31) - the sequence itself.
Output
On the first line of the output print L - the length of the greatest common increasing subsequence of both sequences. On the second line print the subsequence itself. If there are several
possible answers, output any of them.
This problem contains multiple test cases!
The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank
line between input blocks.
The output format consists of N output blocks. There is a blank line between output blocks.
Sample Input
1
5
1 4 2 5 -12
4
-12 1 2 4
Sample Output
2
1 4
Source: Northeastern Europe 2003, Northern Subregion
Submit Status
记录路径
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 505;
int n, m, t, a[maxn], b[maxn], dp[maxn][maxn], pathx[maxn][maxn], pathy[maxn][maxn], cur, ans;
void Printf(int x, int y)
{
if(dp[x][y] == 0)
return;
if(pathx[x][y] != -1 && pathy[x][y] != -1)
{
int tx = pathx[x][y];
int ty = pathy[x][y];
Printf(tx, ty);
if(dp[x][y] != dp[tx][ty] && y != 0)
{
cur++;
if(cur < ans)
printf("%d ", b[y]);
else
printf("%d\n", b[y]);
}
}
}
int main()
{
cin >> t;
while(t--)
{
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
scanf("%d", &m);
for(int i = 1; i <= m; i++) scanf("%d", &b[i]);
memset(dp, 0, sizeof(dp));
memset(pathx, -1, sizeof(pathx));
memset(pathy, -1, sizeof(pathy));
int tmpx = 0, tmpy = 0;
for(int i = 1; i <= n; i++)
{
tmpx = 0, tmpy = 0;
int maxx = 0;
for(int j = 1; j <= m; j++)
{
dp[i][j] = dp[i-1][j];
pathx[i][j] = i-1;
pathy[i][j] = j;
if(a[i] > b[j] && maxx < dp[i-1][j]) maxx = dp[i-1][j], tmpx = i-1, tmpy = j;
if(a[i] == b[j]) dp[i][j] = maxx+1, pathx[i][j] = tmpx, pathy[i][j] = tmpy;
}
}
ans = 0;
int flag = -1;
for(int i = 1; i <= m; i++)
{
if(ans < dp
[i])
{
flag = i;
ans = dp
[i];
}
}
printf("%d\n", ans);
tmpx = n, tmpy = flag;
cur = 0;
if(tmpy > 0)
Printf(tmpx, tmpy);
if(t != 0)
puts("");
}
return 0;
}
Greatest Common Increasing Subsequence
Time Limit: 2 Seconds Memory Limit: 65536 KB Special Judge
You are given two sequences of integer numbers. Write a program to determine their common increasing subsequence of maximal
possible length.
Sequence S1, S2, ..., SN of length 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 (-2^31 <= Ai < 2^31) - the sequence itself.
Output
On the first line of the output print L - the length of the greatest common increasing subsequence of both sequences. On the second line print the subsequence itself. If there are several
possible answers, output any of them.
This problem contains multiple test cases!
The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank
line between input blocks.
The output format consists of N output blocks. There is a blank line between output blocks.
Sample Input
1
5
1 4 2 5 -12
4
-12 1 2 4
Sample Output
2
1 4
Source: Northeastern Europe 2003, Northern Subregion
Submit Status
相关文章推荐
- zoj 2432 && hdoj 1423 Greatest Common Increasing Subsequence 【打印LCIS】
- HDU 4421 & ZOJ 3556 Bit Magic(2-SAT 位运算 模板题)
- hdu 1423 最长上升公共子序列 LCIS 模板题
- zoj2432 hdoj1423 最长公共上升子序列(LCIS)
- HDU1423&ZOJ2432 - Greatest Common Increasing Subsequence(LCIS最长公共上升子序列模板)
- ZOJ 1108 FatMouse's Speed (HDU 1160) DP
- 【hdu 1863】畅通工程(最小生成树&克鲁斯卡尔算法模板)
- HDU 1423 最长上升公共子序列(LCIS)
- HDU 4118 && ZOJ 3659
- HDU 1166 树状数组&&线段树模板1
- zoj 2107&&hdu 1007最近点对问题
- Penney's game (hdu 5169, zoj 3274)
- zoj 3726& hdu 4791 Alice's Print Service
- POJ 2777 && ZOJ 1610 &&HDU 1698 --线段树--区间更新
- hdu 1052&ZOJ 2397 Tian Ji -- The Horse Racing
- <模板> Hdu 1402 A * B Problem Plus 大数乘法
- ZOJ 4772 Treasure Hunt I 树形DP(背包) && hdu The Ghost Blows Light 树形DP(背包)
- hdu 1425 快排&模板
- hdu 1160 || zoj 1108 FatMouse's Speed
- ZOJ 3547 & HDU 4059