最长上升子序列
标签(空格分隔): ACM题目 动态规划
POJ_百练_2757:最长上升子序列
描述
一个数的序列
bi
b
i
,当
b1<b2<...<bS
b
1
<
b
2
<
.
.
.
<
b
S
的时候,我们称这个序列是上升的。对于给定的一个序列
(a1,a2,...,aN)
(
a
1
,
a
2
,
.
.
.
,
a
N
)
,我们可以得到一些上升的子序列
(ai1,ai2,...,aiK)
(
a
i
1
,
a
i
2
,
.
.
.
,
a
i
K
)
,这里
1<=i1<i2<...<iK<=N
1
<=
i
1
<
i
2
<
.
.
.
<
i
K
<=
N
。比如,对于序列
(1,7,3,5,9,4,8),
(
1
,
7
,
3
,
5
,
9
,
4
,
8
)
,
有它的一些上升子序列,如
(1,7),(3,4,8)
(
1
,
7
)
,
(
3
,
4
,
8
)
等等。这些子序列中最长的长度是
4
4
,比如子序列.
你的任务,就是对于给定的序列,求出最长上升子序列的长度。
输入
输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000。
输出
最长上升子序列的长度。
样例输入
7
1 7 3 5 9 4 8
样例输出
4
来源
翻译自 Northeastern Europe 2002, Far-Eastern Subregion 的比赛试题
问题建模:
输入:
N,N∈[1,1000]
N
,
N
∈
[
1
,
1000
]
代表序列的长度
a(i),i∈[1,N]
a
(
i
)
,
i
∈
[
1
,
N
]
代表序列中第
i
i
个元素的值
输出:
代表序列中最长子序列的长度.
找子问题:
“求序列的前
n
n
个元素的最长上升子序列的长度”是和原问题相同的一个子问题,但是不具有”无后效性”.
假设, 但可能前
n
n
个元素中有多个序列满足,比如前
n
n
个元素中有序列,的长度均为
x
x
,即都满足,那么可能序列
B1
B
1
中的最后一个元素比
an+1
a
n
+
1
大,那么此时
F(n+1)=x+1
F
(
n
+
1
)
=
x
+
1
,也有可能
B2
B
2
中的最后一个元素不比
a(n+1)
a
(
n
+
1
)
小,那么
F(n+1)=x
F
(
n
+
1
)
=
x
,也就是说计算
F(n+1)
F
(
n
+
1
)
的时候我需要知道计算
F(n)
F
(
n
)
时候的得到的所有序列.这显然是不满足无后效性的设计.
满足无后效性的设计要求: 计算第 n+1 n + 1 个状态的时候,也就是计算 F(n+1) F ( n + 1 ) 的时候,我只需要知道 F(n) F ( n ) ,但是不需要知道计算第 n n 个状态的时候的计算过程.计算第个状态的计算过程和计算第 n+1 n + 1 个状态无关.
好的设计方法
考虑”以第
k
k
个元素作为终点计算得到最长上升子序列的长度”.这个子问题的形式和原问题并不完全一样.但是它的状态的计算是满足无后效性原则的.求出以第个元素作为终点的最长上升子序列长度,在这
n
n
个状态中找到最大的值便是原问题的解.
递推方程:
以
k
k
作为终点的最长上升子序列的长度.
maxLen(k)=0,k∈[2,N]
m
a
x
L
e
n
(
k
)
=
0
,
k
∈
[
2
,
N
]
计算,当
k∈[2,N]
k
∈
[
2
,
N
]
时有:
ans=max1≤k≤N{maxLen(k)} a n s = max 1 ≤ k ≤ N { m a x L e n ( k ) }
实例计算:
N=7
N
=
7
a1=1,a2=7,a3=3,a4=5,a5=9,a6=4,a7=8
a
1
=
1
,
a
2
=
7
,
a
3
=
3
,
a
4
=
5
,
a
5
=
9
,
a
6
=
4
,
a
7
=
8
代入递推公式计算
maxLen(k),k∈[1,N]
m
a
x
L
e
n
(
k
)
,
k
∈
[
1
,
N
]
maxLen(1)=1
m
a
x
L
e
n
(
1
)
=
1
计算以第二个元素作为终点的最长序列长度:
maxLen(2)=0
m
a
x
L
e
n
(
2
)
=
0
maxLen(2)1=max{maxLen(2),maxLen(1)+1}=2,a(2)>a(1)成立
m
a
x
L
e
n
(
2
)
1
=
max
{
m
a
x
L
e
n
(
2
)
,
m
a
x
L
e
n
(
1
)
+
1
}
=
2
,
a
(
2
)
>
a
(
1
)
成
立
maxLen(2)=2
m
a
x
L
e
n
(
2
)
=
2
计算以第三个元素作为终点的最长序列长度:
maxLen(3)=0
m
a
x
L
e
n
(
3
)
=
0
maxLen(3)1=max{maxLen(3),maxLen(1)+1}=2,a(3)>a(1)成立
m
a
x
L
e
n
(
3
)
1
=
max
{
m
a
x
L
e
n
(
3
)
,
m
a
x
L
e
n
(
1
)
+
1
}
=
2
,
a
(
3
)
>
a
(
1
)
成
立
maxLen(3)=2
m
a
x
L
e
n
(
3
)
=
2
maxLen(3)2=max{maxLen(3),1}=2,a(3)≤a(2)成立
m
a
x
L
e
n
(
3
)
2
=
max
{
m
a
x
L
e
n
(
3
)
,
1
}
=
2
,
a
(
3
)
≤
a
(
2
)
成
立
maxLen(3)=2
m
a
x
L
e
n
(
3
)
=
2
计算以第四个元素作为终点的最长序列长度:
maxLen(4)=0
m
a
x
L
e
n
(
4
)
=
0
maxLen(4)1=max{maxLen(4),maxLen(1)+1}=2,a(4)>a(1)成立
m
a
x
L
e
n
(
4
)
1
=
max
{
m
a
x
L
e
n
(
4
)
,
m
a
x
L
e
n
(
1
)
+
1
}
=
2
,
a
(
4
)
>
a
(
1
)
成
立
maxLen(4)=2
m
a
x
L
e
n
(
4
)
=
2
maxLen(4)2=max{maxLen(4),1}=2,a(4)≤a(2)成立
m
a
x
L
e
n
(
4
)
2
=
max
{
m
a
x
L
e
n
(
4
)
,
1
}
=
2
,
a
(
4
)
≤
a
(
2
)
成
立
maxLen(4)=2
m
a
x
L
e
n
(
4
)
=
2
maxLen(4)3=max{maxLen(4),maxLen(3)+1}=3,a(4)>a(3)成立
m
a
x
L
e
n
(
4
)
3
=
max
{
m
a
x
L
e
n
(
4
)
,
m
a
x
L
e
n
(
3
)
+
1
}
=
3
,
a
(
4
)
>
a
(
3
)
成
立
maxLen(4)=3
m
a
x
L
e
n
(
4
)
=
3
计算以第五个元素作为终点的最长序列长度:
maxLen(5)=0
m
a
x
L
e
n
(
5
)
=
0
maxLen(5)1=max{maxLen(5),maxLen(1)+1}=2,a(5)>a(1)成立
m
a
x
L
e
n
(
5
)
1
=
max
{
m
a
x
L
e
n
(
5
)
,
m
a
x
L
e
n
(
1
)
+
1
}
=
2
,
a
(
5
)
>
a
(
1
)
成
立
maxLen(5)=2
m
a
x
L
e
n
(
5
)
=
2
maxLen(5)2=max{maxLen(5),maxLen(2)+1}=3,a(5)>a(2)成立
m
a
x
L
e
n
(
5
)
2
=
max
{
m
a
x
L
e
n
(
5
)
,
m
a
x
L
e
n
(
2
)
+
1
}
=
3
,
a
(
5
)
>
a
(
2
)
成
立
maxLen(5)=3
m
a
x
L
e
n
(
5
)
=
3
maxLen(5)3=max{maxLen(5),maxLen(3)+1}=3,a(5)>a(3)成立
m
a
x
L
e
n
(
5
)
3
=
max
{
m
a
x
L
e
n
(
5
)
,
m
a
x
L
e
n
(
3
)
+
1
}
=
3
,
a
(
5
)
>
a
(
3
)
成
立
maxLen(5)=3
m
a
x
L
e
n
(
5
)
=
3
maxLen(5)4=max{maxLen(5),maxLen(4)+1}=2,a(5)>a(4)成立
m
a
x
L
e
n
(
5
)
4
=
max
{
m
a
x
L
e
n
(
5
)
,
m
a
x
L
e
n
(
4
)
+
1
}
=
2
,
a
(
5
)
>
a
(
4
)
成
立
maxLen(5)=4
m
a
x
L
e
n
(
5
)
=
4
计算以第六个元素作为终点的最长序列长度:
maxLen(6)=0
m
a
x
L
e
n
(
6
)
=
0
maxLen(6)1=max{maxLen(6),maxLen(1)+1}=2,a(6)>a(1)成立
m
a
x
L
e
n
(
6
)
1
=
max
{
m
a
x
L
e
n
(
6
)
,
m
a
x
L
e
n
(
1
)
+
1
}
=
2
,
a
(
6
)
>
a
(
1
)
成
立
maxLen(6)=2
m
a
x
L
e
n
(
6
)
=
2
maxLen(6)2=max{maxLen(6),1}=2,a(6)≤a(2)成立
m
a
x
L
e
n
(
6
)
2
=
max
{
m
a
x
L
e
n
(
6
)
,
1
}
=
2
,
a
(
6
)
≤
a
(
2
)
成
立
maxLen(6)=2
m
a
x
L
e
n
(
6
)
=
2
maxLen(6)3=max{maxLen(6),maxLen(3)+1}=3,a(6)>a(3)成立
m
a
x
L
e
n
(
6
)
3
=
max
{
m
a
x
L
e
n
(
6
)
,
m
a
x
L
e
n
(
3
)
+
1
}
=
3
,
a
(
6
)
>
a
(
3
)
成
立
maxLen(6)=3
m
a
x
L
e
n
(
6
)
=
3
maxLen(6)4=max{maxLen(6),1}=3,a(6)≤a(4)成立
m
a
x
L
e
n
(
6
)
4
=
max
{
m
a
x
L
e
n
(
6
)
,
1
}
=
3
,
a
(
6
)
≤
a
(
4
)
成
立
maxLen(6)=3
m
a
x
L
e
n
(
6
)
=
3
maxLen(6)5=max{maxLen(6),1}=3,a(6)≤a(5)成立
m
a
x
L
e
n
(
6
)
5
=
max
{
m
a
x
L
e
n
(
6
)
,
1
}
=
3
,
a
(
6
)
≤
a
(
5
)
成
立
maxLen(6)=3
m
a
x
L
e
n
(
6
)
=
3
计算以第七个元素作为终点的最长序列长度:
maxLen(7)=0
m
a
x
L
e
n
(
7
)
=
0
maxLen(7)1=max{maxLen(7),maxLen(1)+1}=2,a(7)>a(1)成立
m
a
x
L
e
n
(
7
)
1
=
max
{
m
a
x
L
e
n
(
7
)
,
m
a
x
L
e
n
(
1
)
+
1
}
=
2
,
a
(
7
)
>
a
(
1
)
成
立
maxLen(7)=2
m
a
x
L
e
n
(
7
)
=
2
maxLen(7)2=max{maxLen(7),maxLen(2)+1}=3,a(7)>a(2)成立
m
a
x
L
e
n
(
7
)
2
=
max
{
m
a
x
L
e
n
(
7
)
,
m
a
x
L
e
n
(
2
)
+
1
}
=
3
,
a
(
7
)
>
a
(
2
)
成
立
maxLen(7)=3
m
a
x
L
e
n
(
7
)
=
3
maxLen(7)3=max{maxLen(7),maxLen(3)+1}=3,a(7)>a(3)成立
m
a
x
L
e
n
(
7
)
3
=
max
{
m
a
x
L
e
n
(
7
)
,
m
a
x
L
e
n
(
3
)
+
1
}
=
3
,
a
(
7
)
>
a
(
3
)
成
立
maxLen(7)=3
m
a
x
L
e
n
(
7
)
=
3
maxLen(7)4=max{maxLen(7),maxLen(4)+1}=4,a(7)>a(4)成立
m
a
x
L
e
n
(
7
)
4
=
max
{
m
a
x
L
e
n
(
7
)
,
m
a
x
L
e
n
(
4
)
+
1
}
=
4
,
a
(
7
)
>
a
(
4
)
成
立
maxLen(7)=4
m
a
x
L
e
n
(
7
)
=
4
maxLen(7)5=max{maxLen(7),1}=4,a(7)≤a(5)成立
m
a
x
L
e
n
(
7
)
5
=
max
{
m
a
x
L
e
n
(
7
)
,
1
}
=
4
,
a
(
7
)
≤
a
(
5
)
成
立
maxLen(7)=4
m
a
x
L
e
n
(
7
)
=
4
maxLen(7)6=max{maxLen(7),maxLen(6)+1}=4,a(7)>a(6)成立
m
a
x
L
e
n
(
7
)
6
=
max
{
m
a
x
L
e
n
(
7
)
,
m
a
x
L
e
n
(
6
)
+
1
}
=
4
,
a
(
7
)
>
a
(
6
)
成
立
maxLen(7)=4
m
a
x
L
e
n
(
7
)
=
4
maxLen(1)=1,maxLen(2)=2,maxLen(3)=2,
m
a
x
L
e
n
(
1
)
=
1
,
m
a
x
L
e
n
(
2
)
=
2
,
m
a
x
L
e
n
(
3
)
=
2
,
maxLen(4)=3,maxLen(5)=4,maxLen(6)=3,maxLen(7)=4
m
a
x
L
e
n
(
4
)
=
3
,
m
a
x
L
e
n
(
5
)
=
4
,
m
a
x
L
e
n
(
6
)
=
3
,
m
a
x
L
e
n
(
7
)
=
4
ans=4
a
n
s
=
4
算法时间复杂度: O(N2) O ( N 2 )
轻松ACCCEPT:
// http://bailian.openjudge.cn/practice/2757
#include <bits/stdc++.h>
using namespace std;
#define MAX_N 1005
int N;
int a[MAX_N], maxLen[MAX_N];
void solve(){
int i,k;
for(i = 1; i <= N; i++) maxLen[i] = 1; // 一开始都是1
for(k = 2; k <= N; k++){ // 以第k个元素作为终点
for(i = 1; i <= k-1; i++){ // 前面
if(a[k] > a[i]) { // 递推公式
maxLen[k] = max(maxLen[k], maxLen[i]+1);
}
}
}
printf("%d\n", *max_element(maxLen+1, maxLen+N+1));
}
int main(){
//freopen("in.txt", "r", stdin);
int i;
while(~scanf("%d", &N) && N){
for(i = 1; i <= N; i++) scanf("%d", &a[i]); // 输入数据
solve();
}
return 0;
}