动态规划 最长上升子序列(LIS)

O(N2)写法:

memset(dp, 0, sizeof(dp))

for(i = 0; i < n; i++) {

         dp[i]= 1;

         for(j= 0; j < i; j++) {

                   if(s[j]< s[i]) dp[i] = max(dp[i], dp[j] + 1);

         }

}

O(nlogn)写法1:( dp[i]存长度为i + 1的上升子序列中末尾元素的最小值)

fill(dp, dp + n, inf);

for(i = 0; i < n; i++) {

         *lower_bound(dp,dp + n, a[i]) = a[i];

}

printf(“%d\n”, lower_bound(dp, dp + n, inf)– dp);

 

O(nlogn)写法2:dp[i]存长度为i的上升子序列中末尾元素的最小值,下标从1开始

         intk = 1;

         b[1]= a[1];

         for(i= 2; i <= n; i++) {

                   if(a[i]> b[k]) {

                            b[++k]= a[i];

                   }

                   else{

                            char*pos = lower_bound(b, b + k,a[i]);

                            *pos= a[i];

                   }

         }

         printf("%d\n",k);


理解算法思想:http://blog.csdn.net/joylnwang/article/details/6766317


几个题目:

nyoj 17 :http://acm.nyist.net/JudgeOnline/problem.php?pid=17

怎么写都可以过


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

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

两道LIS裸题,nlogn 都可以过

#include 
#include 
#include 
#include 
#include 
using namespace std;
int a[100100], b[100100];
int main() {
	int n;
	while(~scanf("%d", &n)) {
		int i, j;
		for(i = 0; i < n; i++) {
			scanf("%d", a + i);
		}
		int k = 0;
		b[0] = a[0];
		for(i = 1; i < n; i++) {
			if(a[i] > b[k]) {
				b[++k] = a[i];
			}
			else {
				*lower_bound(b, b + k, a[i]) = a[i];
			}
		}
		printf("%d\n", k + 1);
	}
	return 0;
}


你可能感兴趣的:(LIS,动态规划,挑战程序设计竞赛)