动态规划使用范围:(http://baike.baidu.com/view/28146.htm)

任何思想方法都有一定的局限性,超出了特定条件,它就失去了作用。同样,动态规划也并不是万能的。适用动态规划的问题必须满足最优化原理和无后效性。   

1.最优化原理(最优子结构性质) 最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质。   

2.无后效性 将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结。这就是无后向性,又称为无后效性。   

3.子问题的重叠性 动态规划将原来具有指数级复杂度的搜索算法改进成了具有多项式时间的算法。其中的关键在于解决冗余,这是动态规划算法的根本目的。 动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其它的算法。

动态规划思想:

如果各个子问题不是独立的,不同的子问题的个数只是多项式量级,如果我们能够保存已经解决的子问题的答案,而在需要的时候再找出已求得的答案,这样就可以避免大量的重复计算。由此而来的基本思路是,用一个表记录所有已解决的子问题的答案,不管该问题以后是否被用到,只要它被计算过,就将其结果填入表中。

时间复杂度为O(n^2),算法原理:

数组a[]为待处理数组

f[]用于记录a[]数组中,以对应位置数据为结尾的最长有序序列长度

p[]用于记录a[]数组中,以对应位置数据为结尾的前一个数据位置

使用position记录最大长度位置

以a[]={1,4,7,2,5,8,3,6,9},计算最长递增有序子序列为例

初始化f[]={1, 1, 1, 1, 1, 1, 1,1,1},p[]={0,1,2,3,4,5,6,7,8}

计算f[i]时,f[i]=max(f[j]+1) ,(其中,a[i]>a[j],i>j>=0),意思是以a[i]为结尾,找出在a[i]前比a[i]小的数据中以该数据为结尾的最大有序子序列长度max(f[j]),则以a[i]结尾的最大有序子序列长度为max(f[j])+1。计算同时定义p[i]=j,标志a[i]为结尾的最长子序列的前一个数据a[j]的位置。同时判断此时最大长度a[i]是否比当前最大长度max大,如果a[i]更大则更新position

a[]={1,4,7,2,5,8,3,6,9}

i=0   f[]={1,1,1,1,1,1,1,1,1},  p[]={0,1,2,3,4,5,6,7,8}

i=1   f[]={1,2,1,1,1,1,1,1,1},  p[]={0,0,2,3,4,5,6,7,8}  4>1,所以最大长度为2,position=1

i=2   f[]={1,2,3,1,1,1,1,1,1},  p[]={0,0,1,3,4,5,6,7,8}  7>4,7>1 其中4结尾的长度为2,所以最大长度为3,position=2

i=3   f[]={1,2,3,2,1,1,1,1,1},  p[]={0,0,1,0,4,5,6,7,8}  2>1 所以最大长度为2

i=4   f[]={1,2,3,2,3,1,1,1,1},  p[]={0,0,1,0,1,5,6,7,8}  5>1,5>4,5>2,其中以4结尾的长度为2,所以最大长度为3

i=5   f[]={1,2,3,2,3,4,1,1,1},  p[]={0,0,1,0,1,2,6,7,8}  8比前面的数据都大,所以最大长度为4,position=5

i=6   f[]={1,2,3,2,3,4,3,1,1},  p[]={0,0,1,0,1,2,3,7,8}  3>1,3>2,其中以2结尾的长度为2,所以最大长度为3

i=7   f[]={1,2,3,2,3,4,3,4,1},  p[]={0,0,1,0,1,2,3,4,8}  6>1,6>4,6>2,6>5,6>3,其中以5结尾长度为3,所以最大长度为4

i=8   f[]={1,2,3,2,3,4,3,4,5},  p[]={0,0,1,0,1,2,3,4,5}  9比前面数据都大,所以最大长度为5,position=8

在对所有a中元素循环过后,通过max记录下最后数据位置,以及p记录的前一个数据的位置,可以递归求出LIS

代码如下:

[cpp] view plaincopy
  1. #include<stdio.h>
  2. int a[10000]={0};
  3. int f[10000]={0};
  4. int p[10000]={0};
  5. int max=0;
  6. int position =0;
  7. void compare(int n){
  8. for(int i=0; i<n; i++){
  9. for(int j=0; j<i; j++){
  10. if(a[i]>a[j]){
  11. if(f[i]<f[j]+1){
  12. f[i]=f[j]+1;
  13. p[i]=j;
  14. if(f[i]>max){
  15. postiion=i;
  16. max = f[i];
  17. }
  18. }
  19. }
  20. }
  21. }
  22. }
  23. void printLIS(int position){
  24. if(p[position]==position){
  25. printf("%d",a[position]);
  26. return;
  27. }
  28. printLIS(p[position]);
  29. printf(" %d",a[position]);
  30. }
  31. void main(){
  32. int n;
  33. max =0;
  34. position = 0;
  35. scanf("%d",&n);
  36. for(int i=0; i<n; i++){
  37. scanf("%d",&a[i]);
  38. f[i]=1;
  39. p[i]=i;
  40. }
  41. compare(n);
  42. printLIS(position);
  43. printf("\n");
  44. }

又如hdoj中的 1160 FatMouse's Speed

Problem Description
FatMouse believes that the fatter a mouse is, the faster it runs. To disprove this, you want to take the data on a collection of mice and put as large a subset of this data as possible into a sequence so that the weights are increasing, but the speeds are decreasing.
Input
Input contains data for a bunch of mice, one mouse per line, terminated by end of file.

The data for a particular mouse will consist of a pair of integers: the first representing its size in grams and the second representing its speed in centimeters per second. Both integers are between 1 and 10000. The data in each test case will contain information for at most 1000 mice.

Two mice may have the same weight, the same speed, or even the same weight and speed.

Output
Your program should output a sequence of lines of data; the first line should contain a number n; the remaining n lines should each contain a single positive integer (each one representing a mouse). If these n integers are m[1], m[2],..., m[n] then it must be the case that

W[m[1]] < W[m[2]] < ... < W[m[n]]

and

S[m[1]] > S[m[2]] > ... > S[m[n]]

In order for the answer to be correct, n should be as large as possible.
All inequalities are strict: weights must be strictly increasing, and speeds must be strictly decreasing. There may be many correct outputs for a given input, your program only needs to find one.

Sample Input
6008 1300 6000 2100 500 2000 1000 4000 1100 3000 6000 2000 8000 1400 6000 1200 2000 1900
Sample Output
4 4 5 9 7

代码如下:

[cpp] view plaincopy
  1. #include<stdio.h>
  2. #include<algorithm>
  3. using namespace std;
  4. int f[10001];
  5. int p[10001];
  6. struct Mouse{
  7. int w;
  8. int s;
  9. int n;
  10. }Mic[10001];
  11. bool compare(const Mouse &a, const Mouse &b){
  12. if(a.w==b.w)
  13. return a.s > b.s;
  14. else
  15. return a.w < b.w;
  16. }
  17. void printLIS(int max_l){
  18. if(p[max_l]==max_l){
  19. printf("%d\n",Mic[max_l].n);
  20. return;
  21. }
  22. printLIS(p[max_l]);
  23. printf("%d\n",Mic[max_l].n);
  24. }
  25. void main(){
  26. int i=1,max=0,max_l=0;
  27. while(scanf("%d %d",&Mic[i].w,&Mic[i].s)!=EOF){
  28. f[i]=1;
  29. p[i]=i;
  30. Mic[i].n=i;
  31. i++;
  32. }
  33. sort(Mic+1,Mic+i,compare);
  34. for(int k=1; k<i+1; k++){
  35. for(int j=1; j<k; j++){
  36. if(Mic[j].s>Mic[k].s&&Mic[j].w<Mic[k].w){
  37. if((f[j]+1)>f[k]){
  38. f[k]=f[j]+1;
  39. p[k]=j;
  40. if(f[k]>max){
  41. max = f[k];
  42. max_l = k;
  43. }
  44. }
  45. }
  46. }
  47. }
  48. printf("%d\n",max);
  49. printLIS(max_l);
  50. }

最长有序子序列—动态规划算法相关推荐

  1. (动态规划 最长有序子序列)Monkey and Banana --HDU --1069

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1069 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  2. 计算机算法设计与分析 动态规划 实验报告,动态规划法解最长公共子序列(计算机算法设计与分析实验报告).doc...

    动态规划法解最长公共子序列(计算机算法设计与分析实验报告) 实报 告 实验名称:任课教师::姓 名:完成日期:二.主要实验内容及要求: 要求按动态规划法原理求解问题: 要求交互输入两个序列数据: 要求 ...

  3. 最长连续子序列nlogn算法

    最长上升子序列(LIS)长度的O(nlogn)算法 标签: 算法search优化存储 2012-04-18 19:38 14031人阅读 评论(5) 收藏 举报  分类: 资料学习(15)  解题报告 ...

  4. 包信封问题 以及 最长有序子序列问题

    https://leetcode.com/problems/russian-doll-envelopes/?tab=Description 包信封问题,可以转化成最长有序子序列问题,见下面的分析: h ...

  5. 北京大学郭炜-最长上升子序列 动态规划讲解

    北京大学郭炜-最长上升子序列 动态规划讲解 问题原型: 解题思路: 找子问题,题目要求我们求1~n的最长上升子序列的长度,那我们想一想:1-2个元素的最长上升子序列的长度是多少,第1个元素的最长上升子 ...

  6. 动态规划——最长公共子序列(算法设计课题)

    问题描述: 若给定序列X={x1,x2,-,xm},则另一序列Z={z1,z2,-,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,-,ik}使得对于所有j=1,2,-,k有:zj=xi ...

  7. python【力扣LeetCode算法题库】300 最长上升子序列(动态规划)

    最长上升子序列 给定一个无序的整数数组,找到其中最长上升子序列的长度. 示例: 输入: [10,9,2,5,3,7,101,18] 输出: 4 解释: 最长的上升子序列是 [2,3,7,101],它的 ...

  8. 夕拾算法进阶篇:15)最长公共子序列(动态规划DP)

    题目描述 给你一个序列X和另一个序列Z,当Z中的所有元素都在X中存在,并且在X中的下标顺序是严格递增的,那么就把Z叫做X的子序列. 例如:Z=<a,b,f,c>是序列X=<a,b,c ...

  9. 最长递增子序列_python_算法与数据结构

    周末了,实验室的网速还是不给力啊,不知道doctors都在干啥,,,最近都在做算法作业,昨天晚上看了一部电影<将爱进行到底>,刚打开电影没多久就听到了很熟悉的旋律,让我很是惊讶,这竟然就是 ...

最新文章

  1. 巧用qmake工具生成专业的makefile
  2. java继承方法规则或规律
  3. android启用hdcp_如何在Android上启用优先收件箱(和设置仅重要通知)
  4. html如何实现切换效果,纯CSS实现页签切换效果
  5. idea 2017 创建java_IDEA2017.3.3创建第一个javaweb项目及tomcat部署实战
  6. linux下文件时间戳
  7. mysql workbench 导出查询结果_MySQL Workbench查询结果导出步骤
  8. 28. git 常用命令
  9. 四 Lync Server 2013 部署指南-前端部署(1)
  10. 科学道德与学风-2021雨课堂答案-第4章
  11. matlab两个力的合成与分解,[转帖]小波图像分解与合成(例子) - Matlab讨论区 - 振动论坛 动力学,噪声 -......
  12. vue中a标签的href属性的写法
  13. UDP传输图片(分包)
  14. C++面向对象程序设计大作业:魔兽世界(三):开战
  15. 腾讯、美团通报反腐情况;马斯克回应:涨价也没人补差价;滴滴出行恢复新用户注册 | EA周报...
  16. 如果有一天不写代码了,还能干点啥?
  17. shell脚本中计算时间差
  18. pytorch(仅供自己参考勿看)
  19. 计算机的收获初一作文,初一开学一个月的收获和感受作文
  20. 学习日语应该先掌握哪些内容?

热门文章

  1. adb 切换默认桌面_公告 | 武林外传手游官方服务器全面开放桌面版体验
  2. java的封装性的优点_18、Java的三大特性之封装
  3. 工业交换机在城市智慧轨道交通中的应用分析
  4. 串口服务器工作方式及常见异常故障问题排除方法介绍
  5. 【渝粤教育】国家开放大学2019年春季 1018国际公法 参考试题
  6. mysql 数据路由_node-路由操作mysql数据库
  7. mysql数据库全备_MySQL innobackupex全备是指什么
  8. java中n次方怎么表示_java如何计算一个数的n次方
  9. android运行的线程中,android中线程是否运行在单独的进程中?
  10. 组合逻辑电路运算法则