最长递减子序列(转载)

Q:例如:有一个序列,例如 9 8 2 1 7 5 3 4 3 2 1.
     求出最长的递减子序列。如本例的结果就是:9 8 7 5 4 3 2 1。

分析:

可采用动态规划的思想进行解答,时间复杂度为O(n^2).

设原数组为a[1....n]。另设一数组d[1....n],其中d[i]表示从第i个元素开始(一定包含第i个元素),到整个数组末尾的子序列 a[i...n]中的最长递减子序列的长度。
       则本问题就是要在求出d[1]的同时,恢复出最优解。

下面给出递推式:

d[i]的值分两种情况:
1、当i=n时,d[i]=1。即最后一个元素的序列的最大递减子序列中只有它自己。

2、当i<n时,d[i]=max{d[k]| i<k<=n 且a[i]>a[k]} +1。解释意思为,包含第i个元素的序列a[i...n]的最大子序列依赖于i后面所有的序列中比a[i]小(满足递减
特性),且最大的d[k](满足最 优特性)值再加1(加上a[i]元素)。在给d[i]赋值的时候只需记录p[i]=k,既可以作为parent属性恢复出解。

具体实现的话,开两个数组d[n],p[n],外层循环从后往前选取i,内层循环从i往后寻找最优的k,双循环遍历即可求出所有的d[i]。然后 再进行一次O(n)操作,找出最大的d[max]。恢复解的话,可以从p[max]开始,依次恢复出各个解。

 #include <iostream.h>
 2
 3 void longest_decrease_sub(int *a, int size)
 4 {
 5
 6     int *d=new int[size]; //分配内存空间
 7     int *p=new int[size];  //分配内存空间
 8
 9     d[size-1]=1;
10
11     for(int i=size-1;i>=0;i--)
12     {
14         int max=0;
16         int index=0;
17
18         for(int j=i;j<size;j++)
19         {
21             if(a[i]>a[j] && max <d[j])
22             {
24                 max=d[j];
26                 index=j;
28             }
30         }
31
32         if(max==0)
33         {
34
35             d[i]=1;
36
37             p[i]=-1;
38
39         }
40         else
41         {
42
43             d[i]=max+1;
45             p[i]=index;
47         }
49     }
51     //寻找最大子序列的起始下标
53     int max=0;
55     int max_index=0;
57     for( i=0;i<size;i++)
58     {
60         if(d[i]>max)
61         {
62
63             max=d[i];
64
65             max_index=i;
66
67         }
69     }
70
71     //从最大子序列的下标开始 输出子序列
72     cout<<"\n最长递减子序列的长度为:"<<d[max_index]<<",最长子序列为:"<<ends;
73
74     for( i=max_index;i!=-1;i=p[i])
75     {
76
77         cout<<a[i]<<" "<<ends;
78
79     }
80
81     delete [] d;
82
83     delete [] p;
84
85 }
86
87 void main()
88 {
89     int data[10]={1,2,5,4,3,2,7,8,9,0};
90     longest_decrease_sub(data,10);
91 }

另外一个代码版本:

 1 #include <iostream>
 2 #include <vector>
 3 using namespace std;
 4
 5
 6 int main()
 7 {
 8     int n,m;
 9     cin>>n;
10     while (n--) {
11         cin>>m;
12         vector<int>b(m);
13         vector<int>f(m);
14         for(int i=0;i<m;i++)
15         {
16             cin>>b[i];
17             f[i]=1;
18         }
19         for(int i=1;i<m;i++)
20             for(int j=0;j<i;j++)
21             {
22                 if(b[j]>=b[i]&&f[j]+1>f[i])
23                     f[i]=f[j]+1;
24             }
25         int max=1;
26         for(int i=0;i<m;i++)
27         {
28             if(f[i]>max)
29                 max=f[i];
30         }
31         cout<<max<<endl;
32     }
33     return 0;
34 }
时间: 2024-10-19 23:52:16

最长递减子序列(转载)的相关文章

最长递减子序列(nlogn)(个人模版)

最长递减子序列(nlogn): 1 int find(int n,int key) 2 { 3 int left=0; 4 int right=n; 5 while(left<=right) 6 { 7 int mid=(left+right)/2; 8 if(res[mid]>key) 9 { 10 left=mid+1; 11 } 12 else 13 { 14 right=mid-1; 15 } 16 } 17 return left; 18 } 19 20 int Lis(int a[

HDU 1160 FatMouse&#39;s Speed (动规+最长递减子序列)

FatMouse's Speed Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 9174    Accepted Submission(s): 4061 Special Judge Problem Description FatMouse believes that the fatter a mouse is, the faster

poj 1952 BUY LOW, BUY LOWER (最长递减子序列+不同子序列计数)

BUY LOW, BUY LOWER Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 8327   Accepted: 2888 Description The advice to "buy low" is half the formula to success in the bovine stock market.To be considered a great investor you must also f

算法 - 求一个数组的最长递减子序列(C++)

//**************************************************************************************************** // // 求一个数组的最长递减子序列 - C++ - by Chimomo // // 题目: 求一个数组的最长递减子序列,比方{8, 14, 6, 2, 8, 14, 3, 2, 7, 4, 7, 2, 8, 101, 23, 6, 1, 2, 1, 1}的最长递减子序列为{14.8,3.

hdu1160最长递减子序列及其路径

FatMouse's Speed Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 9069    Accepted Submission(s): 4022Special Judge Problem Description FatMouse believes that the fatter a mouse is, the faster it

【编程题目】求一个数组的最长递减子序列 比如{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5, 4,3,2}

47.创新工场(算法):求一个数组的最长递减子序列 比如{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5,4,3,2} 思路:动态规划 从最后一个数字开始,计算以当前数字其实的序列的最长递减子序列. 每次找最长子序列,都扫描它之前求得的子序列中最长,且第一个数字比当前数字小的. 如: 第一个数字 2, 最大长度 1, 下一个数字是 第 7 个 第二个数字 3,  最大长度 2, 下一个数字是 第 7 个 第三个数字 4,  最大长度 3, 下一个数字是 第 6 个 第四个数字 5, 

UVa 10285 Longest Run on a Snowboard(DP 二维最长递减子序列)

题意  输入一个城市的滑雪地图  你可以从高的地方滑到伤下左右低的地方  求这个城市的最长滑雪线路长度   即在一个矩阵中找出最长递减连续序列 令d[i][j]为以格子map(i,j)为起点的最长序列   则有状态转移方程d[i][j]=max{d[a][b]}+1  a,b为与i,j相邻且值比i,j小的所有点 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #def

HDU 1257 最少拦截系统(最长递减子序列的条数)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1257 题解: 1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 5 const int maxn = 1000 + 10; 6 7 int dp[maxn],arr[maxn]; 8 int n; 9 10 int main() { 11 while (scanf("%d", &

最长递增子序列和网易去除最少使从左向右递增又递减问题

(1)最长递增子序列问题 有两种方法:(1)动态规划方法(2)类似二分查找的方法O(nlogn) 动态规划方法: 以i结尾的序列的最长递增子序列和其[0, i - 1]“前缀”的最长递增子序列有关,设LIS[i]保存以i结尾的最长递增子序列的长度:     若i = 0,则LIS[i] = 1:     若i > 0,则LIS[i]的值和其[0, i - 1]前缀的最长递增子序列长度有关,用j遍历[0, i - 1]得到其最长递增子序列为LIS[j],对每一个LIS[j],如果序列array[j