动态规划(线性模型):POJ 1631 最长上升子序列

这道题如果采用和第2533题一样O(n^2)的方法会超时。下面贴出TLE的代码。#include <cstdio> #include <cstring> #define MAX 40001 using namespace std; int dp[MAX]; int seq[MAX]; int DP(int s[], int n) { int i, j, max; for (i=1; i<=n; i++) { max = 0; for (j=1; j<i; j++) { if (seq[i] > seq[j]) { if (dp[j] > max) { max = dp[j]; } } } dp[i] = max + 1; } max = dp[1]; for (i=1; i<=n; i++) { if (dp[i] > max) { max = dp[i]; } } return max; } int main(void) { int n, p, temp; scanf("%d", &n); while (n-- > 0) { scanf("%d", &p); temp = 1; while(p-- > 0) { scanf("%d", &seq[temp++]); } printf("%d/n", DP(seq, temp-1)); memset(seq, 0, sizeof(int) * MAX); } return 0; }
第二种方法是二分+贪心的思路。这种方法需要维护一个栈,并且栈内的元素按升序排列。每当读取seq中的一个元素时,如果该元素比栈顶元素大,则直接push入栈。否则,在栈中找到第一个比该元素大的数,用该元素替换之。这样,用一个较小的元素替换栈中一个较大的元素,那么这个序列的“潜力”就变大了。最后最大序列的长度,即为栈的长度。由于是二分查找,这种方法的复杂度为O(nlogn)#include <cstdio> #include <cstring> #define MAX 40001 using namespace std; int stack[MAX]; int seq[MAX]; void search(int b, int e, int num) { if (b > e) { return; } else if (b == e) { if (stack[b] > num) { stack[b] = num; } } else { int half = (b + e) / 2; if (stack[half] > num) { search(b, half, num); } else { search(half+1, e, num); } } } int DP(int s[], int n) { int i, size = 0; for (i=1; i<=n; i++) { if (size == 0) { stack[1] = seq[i]; size++; } else if (seq[i] > stack[size]) { stack[size + 1] = seq[i]; size++; } else if (seq[i] < stack[size]) { search(1, size, seq[i]); } } return size; } int main(void) { int n, p, temp; scanf("%d", &n); while (n-- > 0) { scanf("%d", &p); temp = 1; while(p-- > 0) { scanf("%d", &seq[temp++]); } printf("%d/n", DP(seq, temp-1)); memset(seq, 0, sizeof(int) * MAX); memset(stack, 0, sizeof(int) * MAX); } return 0; }

你可能感兴趣的:(动态规划(线性模型):POJ 1631 最长上升子序列)