DP-LIS( Longest Increasing Subsequenc)

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++;
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值