最长上升子序列(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 }