动态规划第一题
2013-02-16 11:18 Dr.Ray 阅读(190) 评论(0) 收藏 举报找一个无序数列中最长的非降序子数列。
此题目中,状态为一维的。
证明这个题目可以用动态规划解决,即证明满足最优性原理(即具有最有子结构)和无后效性。
证明满足最优性原理:
这一块我目前还不太清晰,试着说明。序列记为{an}
对于前i-1个数,最长非降序子序列用到ak,长度为c,那么加入ai后长度为c+1或c,则前i 个数中最长子序列长度还是c或c+1
对于前k-1个数,同上。
于是,在前j个数中,最长子序列长度为q,那么q或q-1为前j-1个数的最长非降序子序列长度,满足最有型原理。
证明满足无后效性:
明显第i个状态只用考虑前i-1个数,遂无后效性。
三要素:
阶段:
按序列角标划分阶段。
状态:
开数组opt[i]储存每个阶段的最长子序列长度。
策略:
找到前i-1中满足ak<=ai且opt[k]最大的一项,使得opt[i]=opt[k]+1;
代码:
#include<stdio.h> #include<stdlib.h> #include<string.h>
int main() { int a[]={2,3,15,16,16,9,5,22,1,17}; int opt[10]; memset(opt, 0, sizeof(opt)); int ans = -1; for(int i=0; i<10; i++) { if(i==0) { opt[i] = 1; } for(int j=0; j<i; j++) { if(a[j]<=a[i] && opt[j]+1>opt[i]) { opt[i] = opt[j]+1; } } } for(int i=0; i<10; i++) { if(opt[i]>ans) { ans = opt[i]; } } printf("%d\n",ans); }
最大的问题出现在如何找到opt[k]最大且ak<=ai,一开始的想法是找到opt[k]最大项,记录k,然后如果不满足ak<=ai那么重新找次大的opt[k],很麻烦。
题解是把前i-1项遍历,寻找满足(a[j]>a[i]&&opt[j]+1>opt[i])的项,于是最后得到满足要求。
可知,当目标元素不容易确定时,把每项都当做目标元素遍历一遍储存到目标状态中,并用目标状态做限定条件,遍历完就能达到目的without知道目标元素的位置。