最长递增子串(LIS)

给定一个序列,要求求出该序列的最长单调子序列, 即 longest increasing subsequence,这是一个经典的动态规划求解问题。

设给定序列为 a[],大小为 n,如何求其最长单调子序列呢?考虑将最长单调子序列的长度作为所求的最优值,最长单调子序列必定以序列a[]中的某一个元素结尾。   

设序列count[i]为以a[i]结尾的最长单调子序列的长度,那么a[]的LIS的长度就是max{count[i]}, 对所有i 。

显然此问题具有最优子结构性质,count[0] = 1, count[i] = max{count[j] | 0 <= j < i, a[j] < a[i]} + 1

 

For Example:POJ1836 http://poj.org/problem?id=1836

题意:给出系列数字,要求删除最少的元素,留下一个最长串,使得任意一个数字都不在两个大于等于它的数字中间,使剩下的满足a1 < a2 < ... < a(i ) <=> a(i+1) > a(i+2) > .. a(n-1) > a(n)

思路:只要从左到右,从右到做各求一次LIS,再枚举中间点求出最大串即可。

 1 #include <iostream>
2
3 using namespace std;
4 int count[1000];
5 int count2[1000];
6 double height[1000];
7
8 int main()
9 {
10 int n,temp=0;
11 cin>>n;
12 for (int i=0;i<n;i++)
13 {
14 cin>>height[i];
15 count[i] = 1; //init
16 count2[i] = 1;
17 }
18
19 for (int i=1;i<1000;i++) //LIS
20 {
21 for (int j=0;j<i;j++)
22 {
23 if(height[i]>height[j])
24 count[i] = max(count[i],count[j]+1);
25 }
26 }
27
28 for (int i=n-2;i>=0;i--)//逆序LIS
29 {
30 for (int j=n-1;j>i;j--)
31 {
32 if(height[i]>height[j])
33 count2[i] =max(count2[i],count2[j]+1);
34 }
35 }
36
37 for (int i=0;i<n;i++) //枚举
38 {
39 for(int j=i+1;j<n;j++)
40 temp = max(temp,count[i]+count2[j]);
41 }
42 cout<<n-temp;
43 return 1;
44 }

POJ2533 http://poj.org/problem?id=2533

题意:我是做了1836后再做这题,无语了。。。。。

 1 #include <iostream>
2
3 using namespace std;
4 int a[1001];
5 int dp[1001];
6
7 int main()
8 {
9 int N;
10
11 cin>>N; //input
12 for (int i=1;i<=N;i++)
13 {
14 cin>>a[i];
15 dp[i] = 1;
16 }
17
18 for (int i=2;i<=N;i++) //LIS
19 {
20 for (int j=1;j<i;j++)
21 {
22 if(a[i]>a[j])
23 dp[i] = max(dp[i],dp[j]+1);
24 }
25 }
26
27 int temp = dp[1]; //output
28 for (int i=1;i<=N;i++)
29 temp = max(temp,dp[i]);
30 cout<<temp;
31
32 return 1;
33 }



转载于:https://www.cnblogs.com/dongjinwei/archive/2011/10/21/2220298.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值