DP-LIS( Longest Increasing Subsequenc)

来源:互联网 发布:软件是什么 编辑:程序博客网 时间:2024/05/17 18:48

http://poj.org/problem?id=2533

O(n*n) 算法的状态转移公式:dp[i] = max{dp[j] + 1}, j < i and a[j] < a[i]. 以i结尾的序列的LIS,等于a[0] - a[i - 1] 序列中的LIS 再加1(a[i])。

O(n*logn)算法:记录以a[i]结尾的,长度为j 的LIS,最小的末尾元素dp[j]。通过二分查找,在dp中找出刚好小于a[i]的元素dp[j].  参见 http://www.felix021.com/blog/read.php?1587

//Accepted#include <iostream>using namespace std;int a[1005];int dp[1005];int main(){int n;cin >>n;for(int i = 0; i < n; ++i) {cin >>a[i];dp[i] = 1;}int len = 1;for(int i = 1; i < n; ++i) {for(int j = 0;j < i; ++j) {if(a[j] < a[i] && dp[i]< dp[j] + 1)dp[i]= dp[j] + 1;}if(len < dp[i])len = dp[i];}cout <<len;return 0;}


另附上Wrong answer的一段代码,以后code过程中要注意

int len = 1;for(int i = 1; i < n; ++i) {int max = 0;for(int j = 0;j < i; ++j) {if(a[j] < a[i] && max < dp[j] + 1)max = dp[j] + 1;}dp[i] = max;if(len < dp[i])len = dp[i];}cout <<len;

在第一个for循环里面,定义了max用来记录dp[j] + 1, j <i 的最大值。题目中给出了序列可以通过,另测试几个也可以。

但是注意,加入根本不进入内层for循环,或者进去了if一直为假,导致dp[i] = 0; e.g. 6 4 5的结果为1,而不是2.


另附上一段O(n*logn)的代码,本来昨天一直Wrong answer,今天回来一次就A了。

for(int i = 1; i <= n; ++i) {cin >>a[i];dp[i] = 0;}int len = 1;dp[1] = a[1];for(int i = 2; i <= n; ++i) {left = 1;right = len;while(left <= right) {mid = (left + right) / 2;if(dp[mid] < a[i])left = mid + 1;else right = mid - 1;}dp[left] = a[i];if(len < left)len++;}



原创粉丝点击