标签:
Title:
http://poj.org/problem?id=2533
Description
Input
Output
Sample Input
7 1 7 3 5 9 4 8
Sample Output
4
这个是经典的动态规划题,像我这种渣渣,连这个都要看好久,好吧,其实简单的DP还好,就是nlogn复杂度的,看了好久。嗯,但是呢,网上的那些代码都没有我写的简洁,好吧,这也是聊以自慰呢。。
思路(1): O(n^2)
令A[i]表示输入第i个元素,D[i]表示从A[1]到A[i]中以A[i]结尾的最长子序列长度。对于任意的0 < j <= i-1,如果A(j) < A(i),则A(i)可以接在A(j)后面形成一个以A(i)结尾的新的最长上升子序列。对于所有的 0 < j <= i-1,我们需要找出其中的最大值。
DP状态转移方程:
D[i] = max{1, D[j] + 1} (j = 1, 2, 3, ..., i-1 且 A[j] < A[i])
解释一下这个方程,i, j在范围内:
如果 A[j] < A[i] ,则D[i] = D[j] + 1
如果 A[j] >= A[i] ,则D[i] = 1
int main(){ int a[SIZE]; int d[SIZE]; int n; cin>>n; for (int i = 0; i < n; i++) cin>>a[i]; int m = INT_MIN; for (int i = 0 ;i < n; i++){ d[i] = 1; for (int j = 0; j < i; j++){ if (a[j] < a[i]) d[i] = max(d[i],d[j]+1); } m = max(m,d[i]); } cout<<m<<endl; //system("pause"); }
(2)nlogn的解法。
重新定义下dp[i]
dp[i] 的意思是所有长度为i+1的LIS中末尾元素的最小值
那么最开始,dp[0] = a[0]
因为dp是一个有序数组,所以每次我们都去这个数组中寻找a[i]的位置,例如dp = {2,4,6},如果a[i] = 5,那么a[i]的位置应该是4~6之间,所以返回index = 2.怎么理解呢,dp[i]的定义!所以a[i] = 5,那么有两个长度的最小值都比a[i]小,那加入a[i],这个长度肯定就是3了,然后这个index=2,同时,比较5和6,我们要选择最小的值。我的搜索代码包含了边界的情况,因此,在主函数中就不需要判断。
int search(int * s, int t,int l, int r){ while (l <= r){ int m = (l + r)/2; if (s[m] == t){ return m; }else if (s[m] < t){ l++; }else{ r--; } } return l; } int main(){ int a[SIZE]; int n; cin>>n; for (int i = 0 ; i < n; i++){ cin>>a[i]; } int stack[SIZE]; fill(stack,stack+SIZE,INT_MAX); stack[0] = a[0]; int cur_index = 1; for (int i = 1; i < n; i++){ int j = search(stack,a[i],0,cur_index); stack[j] = min(stack[j],a[i]); if (j == cur_index) cur_index++; } cout<<cur_index; //system("pause"); }
标签:
原文地址:http://www.cnblogs.com/yxzfscg/p/4472491.html