最长上升子序列(LIS)题目合集

有关最长上升子序列的详细算法解释在http://www.cnblogs.com/denghaiquan/p/6679952.html

1)51nod 1134

  一题裸的最长上升子序列,由于N<=50000,n2算法会超时,只能用nlogn算法。

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <vector>
 7 #include <map>
 8 #include <set>
 9 #include <queue>
10 #include <sstream>
11 #include <algorithm>
12 using namespace std;
13 #define pb push_back
14 #define mp make_pair
15 #define ms(a, b)  memset((a), (b), sizeof(a))
16 //#define LOCAL
17 typedef long long LL;
18 const int inf = 0x3f3f3f3f;
19 const int maxn = 50000+10;
20 const LL mod = 1000000000+7;
21 int a[maxn];
22 int dp[maxn];
23 int Binary_search(int key, int len)
24 {
25     int l=1, r=len+1;
26     while(l<r)
27     {
28         int middle = (l+r) >> 1;
29         if(key>=dp[middle])
30             l = middle +1;
31         else
32             r = middle;
33     }
34     return l;
35 }
36 int main()
37 {
38     #ifdef LOCAL
39         freopen("input.txt" , "r", stdin);
40     #endif // LOCAL
41         int n, len;
42         scanf("%d", &n);
43         for(int i=0;i<n;i++)    scanf("%d", &a[i]);
44         dp[1] = a[0];
45         len = 1;
46         for(int i=1;i<n;i++)
47         {
48             if(a[i] > dp[len])
49                 dp[++len] = a[i];
50             else{
51                 int j = Binary_search(a[i], len);
52                 dp[j] = a[i];
53             }
54         }
55         printf("%d\n", len);
56     return 0;
57 }

2)POJ 2533

  裸的最长上升子序列,N<=1000, n2算法可以过。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <vector>
 7 #include <map>
 8 #include <set>
 9 #include <queue>
10 #include <sstream>
11 #include <algorithm>
12 using namespace std;
13 #define pb push_back
14 #define mp make_pair
15 #define ms(a, b)  memset((a), (b), sizeof(a))
16 //#define LOCAL
17 typedef long long LL;
18 const int inf = 0x3f3f3f3f;
19 const int maxn = 1000+10;
20 const LL mod = 1000000000+7;
21 int a[maxn];
22 int dp[maxn];
23 int main()
24 {
25     #ifdef LOCAL
26         freopen("input.txt" , "r", stdin);
27     #endif // LOCAL
28     int n;
29     scanf("%d", &n);
30     for(int i=0;i<n;i++)    scanf("%d", &a[i]);
31     dp[0]=1;
32     for(int i=1;i<n;i++)
33     {
34         dp[i] = 1;
35         for(int j=0;j<i;j++)
36         {
37             if(a[j]<a[i] && dp[j]+1 > dp[i])
38                 dp[i] = dp[j] + 1;
39         }
40     }
41     int ans = 0;
42     for(int i=0;i<n;i++)    ans = max(ans, dp[i]);
43     printf("%d\n", ans);
44     return 0;
45 }

3)POJ 1631

  一题裸的最长上升子序列,由于N<=50000,n2算法会超时,只能用nlogn算法。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <vector>
 7 #include <map>
 8 #include <set>
 9 #include <queue>
10 #include <sstream>
11 #include <algorithm>
12 using namespace std;
13 #define pb push_back
14 #define mp make_pair
15 #define ms(a, b)  memset((a), (b), sizeof(a))
16 //#define LOCAL
17 typedef long long LL;
18 const int inf = 0x3f3f3f3f;
19 const int maxn = 40000+10;
20 const LL mod = 1000000000+7;
21 int a[maxn];
22 int dp[maxn];
23 int Binary_search(int key, int len)
24 {
25     int l=1, r=len+1;
26     while(l<r)
27     {
28         int middle = (l+r) >> 1;
29         if(key>=dp[middle])
30             l = middle +1;
31         else
32             r = middle;
33     }
34     return l;
35 }
36 int main()
37 {
38     #ifdef LOCAL
39         freopen("input.txt" , "r", stdin);
40     #endif // LOCAL
41     int T;
42     scanf("%d", &T);
43     while(T--)
44     {
45         ms(dp, 0);
46         ms(a, 0);
47         int n, len;
48         scanf("%d", &n);
49         for(int i=0;i<n;i++)    scanf("%d", &a[i]);
50         dp[1] = a[0];
51         len = 1;
52         for(int i=1;i<n;i++)
53         {
54             if(a[i] > dp[len])
55                 dp[++len] = a[i];
56             else{
57                 int j = Binary_search(a[i], len);
58                 dp[j] = a[i];
59             }
60         }
61         printf("%d\n", len);
62     }
63     return 0;
64 }

4)POJ 1887

  这题是找最长下不上升子序列。发现n2算法可以过。不过要注意输出。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <vector>
 7 #include <map>
 8 #include <set>
 9 #include <queue>
10 #include <sstream>
11 #include <algorithm>
12 using namespace std;
13 #define pb push_back
14 #define mp make_pair
15 #define ms(a, b)  memset((a), (b), sizeof(a))
16 //#define LOCAL
17 typedef long long LL;
18 const int inf = 0x3f3f3f3f;
19 const int maxn = 32767+10;
20 const LL mod = 1000000000+7;
21 int a[maxn];
22 int dp[maxn];
23 int main()
24 {
25     #ifdef LOCAL
26         freopen("input.txt" , "r", stdin);
27     #endif // LOCAL
28     int t=1;
29     while(scanf("%d", &a[0])&&a[0]!=-1)
30     {
31         if(t>1) printf("\n");
32         int n =1, ans = 0 ;
33         while(scanf("%d", &a[n])&&a[n]!=-1) n++;
34         dp[0]  = 1;
35         for(int i=1;i<n;i++)
36         {
37             dp[i] = 1;
38             for(int j=0;j<n;j++)
39             {
40                 if(a[j] > a[i] && dp[j]+1 > dp[i])
41                     dp[i] = dp[j] + 1;
42             }
43         }
44         for(int i=0;i<n;i++)    ans = max(ans, dp[i]);
45         printf("Test #%d:\n",t++);
46         printf("  maximum possible interceptions: %d\n", ans);
47         ms(a, 0);
48         ms(dp, 0);
49     }
50     return 0;
51 }

5)POJ 1609

  这题同样是最长不上升子序列,不过是2个关键词,先排序一个,再在另一个里面找最长不上升子序列。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <vector>
 7 #include <map>
 8 #include <set>
 9 #include <queue>
10 #include <sstream>
11 #include <algorithm>
12 using namespace std;
13 #define pb push_back
14 #define mp make_pair
15 #define ms(a, b)  memset((a), (b), sizeof(a))
16 //#define LOCAL
17 typedef long long LL;
18 const int inf = 0x3f3f3f3f;
19 const int maxn = 10000+10;
20 const LL mod = 1000000000+7;
21 int a[maxn];
22 int dp[maxn];
23 struct node
24 {
25     int l, m;
26 };
27 bool cmp(node x1, node x2)
28 {
29     if(x1.l != x2.l)
30         return x1.l > x2.l;
31     return x1.m > x2.m;//当第一个关键字相同的时候,第2个关键字要从大到小排序
32 }
33 int main()
34 {
35     #ifdef LOCAL
36         freopen("input.txt" , "r", stdin);
37     #endif // LOCAL
38     int n;
39     while(scanf("%d", &n))
40     {
41         if(n == 0) {printf("*\n");break;}
42         node blocks[maxn];
43         for(int i = 0;i < n;i++)    scanf("%d%d", &blocks[i].l, &blocks[i].m);
44         sort(blocks, blocks+n, cmp);
45         dp[0] = 1;
46         for(int i=1;i<n;i++)
47         {
48             dp[i] = 1;
49             for(int j = 0;j<i;j++)
50             {
51                 if(blocks[j].m >= blocks[i].m && dp[j] + 1 > dp[i])
52                     dp[i] = dp[j]+1;
53             }
54         }
55         int ans = 0;
56         for(int i=0;i<n;i++)    ans = max(ans, dp[i]);
57         printf("%d\n", ans);
58         ms(dp, 0);
59     }
60     return 0;
61 }

 

时间: 2024-12-18 17:36:43

最长上升子序列(LIS)题目合集的相关文章

动态规划(DP),最长递增子序列(LIS)

题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(dp[k])+1,(k<i),(a[k]<a[i]) #include <stdio.h> #define MAX 1005 int a[MAX];///存数据 int dp[MAX];///dp[i]表示以a[i]为结尾的最长递增子序列(LIS)的长度 int main() { int

最长上升子序列LIS解法(n^n &amp;&amp; nlogn)

最长递增子序列问题 在一列数中寻找一些数满足 任意两个数a[i]和a[j] 若i<j 必有a[i]<a[j] 这样最长的子序列称为最长递增子序列LIS LIS问题有两种常见的解法 一种时间复杂度n^n 一种时间复杂度nlogn 下面我们先来说一下n^n的算法 设dp[i]表示以i结尾的最长上升子序列的长度 把问题分解 分解成序列中每一项最为终点的最大上升子序列 从第二项开始依次判断 最后找出最大的一项就是答案 则状态转移方程为 dp[i] = max{dp[j]+1}, 1<=j<

poj1836——dp,最长上升子序列(lis)

poj1836——dp,最长上升子序列(lis) Alignment Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 13767   Accepted: 4450 Description In the army, a platoon is composed by n soldiers. During the morning inspection, the soldiers are aligned in a straight

最长上升子序列LIS模板

1 ///最长上升子序列LIS模板 2 int BinSerch(int l,int r,int cut) 3 { 4 while (l<=r) 5 { 6 int m=(l+r)>>1; 7 if (cut>d[m]&&cut<=d[m+1]) return m; 8 if (cut>d[m]) l=m+1; 9 else r=m-1; 10 } 11 return 0; 12 } 13 14 int LIS(int n) 15 { 16 int le

[kuangbin带你飞]专题十二 基础DP1 N - Longest Ordered Subsequence POJ - 2533(最长上升子序列LIS)

N - Longest Ordered Subsequence POJ - 2533 题目链接:https://vjudge.net/contest/68966#problem/N 题目: 最长有序子序列如果a1 <a2 <... <aN,则排序ai的数字序列. 让给定数字序列(a1,a2,...,aN)的子序列为任何序列(ai1,ai2,...,aiK),其中1 <= i1 <i2 <... <iK <= N 例如,序列(1,7,3,5,9,4,8)具有有

算法--字符串:最长递增子序列LIS

转自:labuladong公众号 很多读者反应,就算看了前文 动态规划详解,了解了动态规划的套路,也不会写状态转移方程,没有思路,怎么办?本文就借助「最长递增子序列」来讲一种设计动态规划的通用技巧:数学归纳思想.  最长递增子序列(Longest Increasing Subsequence,简写 LIS)是比较经典的一个问题,比较容易想到的是动态规划解法,时间复杂度 O(N^2),我们借这个问题来由浅入深讲解如何写动态规划. 比较难想到的是利用二分查找,时间复杂度是 O(NlogN),我们通过

算法面试题 之 最长递增子序列 LIS

找出最长递增序列 O(NlogN)(不一定连续!) 参考 http://www.felix021.com/blog/read.php?1587%E5%8F%AF%E6%98%AF%E8%BF%9E%E6%95%B0%E7%BB%84%E9%83%BD%E6%B2%A1%E7%BB%99%E5%87%BA%E6%9D%A5 我就是理解了一下他的分析 用更通俗易懂的话来说说题目是这样 d[1..9] = 2 1 5 3 6 4 8 9 7 要求找到最长的递增子序列首先用一个数组b[] 依次的将d里面

最长递增子序列 LIS 时间复杂度O(nlogn)的Java实现

关于最长递增子序列时间复杂度O(n^2)的实现方法在博客http://blog.csdn.net/iniegang/article/details/47379873(最长递增子序列 Java实现)中已经做了实现,但是这种方法时间复杂度太高,查阅相关资料后我发现有人提出的算法可以将时间复杂度降低为O(nlogn),这种算法的核心思想就是替换(二分法替换),以下为我对这中算法的理解: 假设随机生成的一个具有10个元素的数组arrayIn[1-10]如[2, 3, 3, 4, 7, 3, 1, 6,

最长上升子序列 (LIS算法(nlong(n)))

设 A[t]表示序列中的第t个数,F[t]表示从1到t这一段中以t结尾的最长上升子序列的长度,初始时设F [t] = 0(t = 1, 2, ..., len(A)).则有动态规划方程:F[t] = max{1, F[j] + 1} (j = 1, 2, ..., t - 1, 且A[j] < A[t]). 现在,我们仔细考虑计算F[t]时的情况.假设有两个元素A[x]和A[y],满足 (1)x < y < t (2)A[x] < A[y] < A[t] (3)F[x] =