题目地址:http://ac.jobdu.com/problem.php?pid=1533

题目描述:

给定一个整型数组, 求这个数组的最长严格递增子序列的长度。 譬如序列1 2 2 4 3 的最长严格递增子序列为1,2,4或1,2,3.他们的长度为3。

输入:

输入可能包含多个测试案例。
对于每个测试案例,输入的第一行为一个整数n(1<=n<=100000):代表将要输入的序列长度
输入的第二行包括n个整数,代表这个数组中的数字。整数均在int范围内。

输出:

对于每个测试案例,输出其最长严格递增子序列长度。

样例输入:
4
4 2 1 3
5
1 1 1 1 1
样例输出:
2
1

参考《编程之美》2.16

对于前面i个元素的任何一个递增子序列,如果这个子序列的最大的元素比array[i+1]小,那么就可以将array[i+1]加在这个子序列后面,构成一个新的子序列。

比如当i=4的时候,目标序列为:1,-1,2,-3,4,-5,6,-7最长递增序列为:(1, 2),(-1, 2)。那么,只要4>2,就可以把4直接增加到前面的子序列中形成一个新的递增子序列。

因此,我们希望找到前i个元素的一个递增子序列,使得这个递增子序列的最大元素比array[i+1]小,且长度尽量地大。这样将array[i+1]加在该递增子序列后,便可找到以array[i+1]为最大元素的最长递增子序列。

仍然假设在数组的前i个元素中,以array[i]为最大元素的最长递增子序列的长度为LIS[i]。

同时,假设:

长度为1的递增子序列最大元素的最小值为MaxV[1];

长度为2的递增子序列最大元素的最小值为MaxV[2];

……

长度为LIS[i]的递增子序列最大元素的最小值为MaxV[LIS[i]]。

具体算法实现如下:

#include <stdio.h>

#define MAX 100000
#define VMAX 100001
#define MIN (-2147483647 - 1) int BSearch (int MaxV[], int start, int end, int key){
int mid; while (start <= end){
mid = start + ((end - start) >> 1);
if (MaxV[mid] < key){
start = mid + 1;
}
else if (MaxV[mid] > key){
end = mid - 1;
}
else
return mid;
}
return start;
} int LIS (int data[], int n){
int MaxV[VMAX];
MaxV[1] = data[0];
MaxV[0] = MIN;
int LIS[MAX]; int nMaxLIS = 1;
int i, j;
for (i=0; i<n; ++i)
LIS[i] = 1;
for (i=1; i<n; ++i){
j = BSearch (MaxV, 0, nMaxLIS, data[i]) - 1;
LIS[i] = j + 1;
if (LIS[i] > nMaxLIS){
nMaxLIS = LIS[i];
MaxV[LIS[i]] = data[i];
}
else if (MaxV[j] < data[i] && data[i] < MaxV[j + 1]){
MaxV[j+1] = data[i];
}
}
return nMaxLIS;
} int main(void){
int data[MAX];
int n;
int i; while (scanf ("%d", &n) != EOF){
for (i=0; i<n; ++i){
scanf ("%d", &data[i]);
}
printf ("%d\n", LIS (data, n));
} return 0;
}

根据参考资料可以知道完全不需要LIS[i]数组去定位,直接用MaxV[i]的下标作为LIS的长度即可。

代码更改如下:

#include <stdio.h>

#define MAX 100000
#define VMAX 100001
#define MIN (-2147483647 - 1) int BSearch (int MaxV[], int start, int end, int key){
int mid; while (start <= end){
mid = start + ((end - start) >> 1);
if (MaxV[mid] < key){
start = mid + 1;
}
else if (MaxV[mid] > key){
end = mid - 1;
}
else
return mid;
}
return start;
} int LIS (int data[], int n){
int MaxV[VMAX];
MaxV[1] = data[0];
MaxV[0] = MIN; int nMaxLIS = 1;
int i, j;
for (i=1; i<n; ++i){
j = BSearch (MaxV, 0, nMaxLIS, data[i]);
if (j > nMaxLIS){
nMaxLIS = j;
MaxV[j] = data[i];
}
else if (MaxV[j-1] < data[i] && data[i] < MaxV[j]){
MaxV[j] = data[i];
}
}
return nMaxLIS;
} int main(void){
int data[MAX];
int n;
int i; while (scanf ("%d", &n) != EOF){
for (i=0; i<n; ++i){
scanf ("%d", &data[i]);
}
printf ("%d\n", LIS (data, n));
} return 0;
}

HDOJ上相似的题目:1025 -- Constructing Roads In JGShining's Kingdom

参考资料:http://www.ahathinking.com/archives/117.html

九度OJ 1533 最长上升子序列 -- 动态规划的更多相关文章

  1. 九度oj 1530 最长不重复子串

    原题链接:http://ac.jobdu.com/problem.php?pid=1530 字符串简单题,看似O(n^2)的复杂度10000的数据量会tle,其实最长不重复子串不超过26个嘛... 如 ...

  2. 九度OJ 1528 最长回文子串 -- Manacher算法

    题目地址:http://ac.jobdu.com/problem.php?pid=1528 题目描述: 回文串就是一个正读和反读都一样的字符串,比如"level"或者"n ...

  3. 九度OJ 1011:最大连续子序列 (DP)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5615 解决:2668 题目描述:     给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, N ...

  4. 九度OJ 1011 最长子串

    #include <iostream> #include <string> #include <sstream> #include <math.h> u ...

  5. 九度oj 1528 最长回文子串

    原题链接:http://ac.jobdu.com/problem.php?pid=1528 小白书上的做法,不过这个还要简单些... #include<algorithm> #includ ...

  6. 九度OJ 1451 不容易系列之一 -- 动态规划

    题目地址:http://ac.jobdu.com/problem.php?pid=1451 题目描述: 大家常常感慨,要做好一件事情真的不容易,确实,失败比成功容易多了! 做好“一件”事情尚且不易,若 ...

  7. 九度OJ 1500 出操队形 -- 动态规划(最长上升子序列)

    题目地址:http://ac.jobdu.com/problem.php?pid=1500 题目描述: 在读高中的时候,每天早上学校都要组织全校的师生进行跑步来锻炼身体,每当出操令吹响时,大家就开始往 ...

  8. 【九度OJ】题目1195:最长&最短文本 解题报告

    [九度OJ]题目1195:最长&最短文本 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1195 题目描述: 输入多行字符串, ...

  9. 【九度OJ】题目1069:查找学生信息 解题报告

    [九度OJ]题目1069:查找学生信息 解题报告 标签(空格分隔): 九度OJ [LeetCode] http://ac.jobdu.com/problem.php?pid=1069 题目描述: 输入 ...

随机推荐

  1. mysql 索引建立

    如何建立mysql索引? 创建索引原则 1.左前缀原则 : mysql索引匹配会从右匹配,到遇到( >  < between like)终止.如 我们建立索引(a,b,c,d), a = ...

  2. Winfrom巧用Using设置鼠标为WaitCursor

    本文转载:http://www.cnblogs.com/LoveJenny/archive/2013/03/13/2956922.html 看到try,finally ,有没有让你想到什么呢?,对了u ...

  3. ThinkPHP3.1快速入门(12)自动验证

    自动验证是ThinkPHP模型层提供的一种数据验证方法,可以在使用create创建数据对象的时候自动进行数据验证. 验证规则 数据验证可以进行数据类型.业务规则.安全判断等方面的验证操作.数据验证有两 ...

  4. 文件和目录之symlink和readlink函数

    symlink函数创建一个符号链接. #include <unistd.h> int symlink( const char *actualpath, const char *sympat ...

  5. LINUX系统备份

    LINUX系统备份 =========================================================== 作者: gswwgph(http://gswwgph.itp ...

  6. Android View的绘制机制流程深入详解(三)

    本系列文章主要着重深入介绍Android View的绘制机制及流程,第三篇主要介绍并分析视图状态以及重绘流程,首先剖析了 视图的几种状态,然后在深入分析视图的重绘机制流程. 真题园网:http://w ...

  7. Android_AutoCompleteTextView,MultiAutoCompleteTextView

    XML布局文件 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:an ...

  8. multithread synchronization use mutex and semaphore

    #include <malloc.h> #include <pthread.h> #include <semaphore.h> struct job { /* Li ...

  9. Greedy

    在现实世界中,有这样一类问题:它有n个输入,而它的解就由这n个输入的某个子集组成,不过这个子集必须满足某些事先给定的条件.把那些必须满足的条件称为约束条件:而把满足约束条件的子集称为该问题的可行解.问 ...

  10. LeetCode里有特色的问题存档

    002* Median of Two Sorted Arrays There are two sorted arrays A and B of size m and n respectively. F ...