关于DP中的最长不下降序列问题分析
2014-02-06 00:22
513 查看
通过一个例子解决两个问题来分析
问题一:求出最长的不下降子序列的长度
问题二:求出最长的不下降子序列,由于最长的子序列可能不一定唯一,那么怎样规定优先循序使得求出的子序列是满足条件的子序列?
例题:
输入有两行,第一行为序列的长度n,第二行为n个序列元素。
Sample Input
14
13 7 9 16 38 24 37 18 44 19 21 22 63 15
Sample Output
8
设nFi 表示从第 项开始(包括第i 项)到最后一项最长不下降子序列的长度,注意 nFi不表示是要求解的最长子序列的长度,因为最长的子序列不一定是从第i 项开始的。如果我们从最后一项开始往前分析,我们有:
![](http://img.blog.csdn.net/20140206001501375?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWF0cml4YTE3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
设nRet表示所要求的最长不下降子序列的长度,那么我们有:
nRet = max{nFi}
参考程序代码:
其次我们来求解【子问题二】
由于最长的子序列可能有多个,我们规定长度相同的子序列按照子序列中元素在原序列中出现的顺序排列,如果相同长度的第一个元素相同(实际上对于不下降子序列问题或者不上升子序列问题,不同的最长子序列中次序位置相同的元素不可能相同!此时只要看第一个元素的位置就可;但对于上升子序列问题或者下降子序列问题,那么次序位置相同的元素可能相同),那么看第二个元素在原序列中的前后位置,如果第二个相同,那可再看第三个元素在原序列中的位置,……,依次类推,我们只要求输出第一个最长的不下降子序列。
参考代码:
问题一:求出最长的不下降子序列的长度
问题二:求出最长的不下降子序列,由于最长的子序列可能不一定唯一,那么怎样规定优先循序使得求出的子序列是满足条件的子序列?
例题:
输入有两行,第一行为序列的长度n,第二行为n个序列元素。
Sample Input
14
13 7 9 16 38 24 37 18 44 19 21 22 63 15
Sample Output
8
设nFi 表示从第 项开始(包括第i 项)到最后一项最长不下降子序列的长度,注意 nFi不表示是要求解的最长子序列的长度,因为最长的子序列不一定是从第i 项开始的。如果我们从最后一项开始往前分析,我们有:
设nRet表示所要求的最长不下降子序列的长度,那么我们有:
nRet = max{nFi}
参考程序代码:
#include<iostream> #include<stdio.h> using namespace std; #define MAX 10001 void vInput(int nArr[],int nN); int nGetLnds(int nArr[],int nN); void vOut(int nOut); int main() { int nData[MAX]; int nNum,nLnds,i; while(cin>>nNum) { vInput(nData,nNum); nLnds=nGetLnds(nData,nNum); vOut(nLnds); } return 0; } void vInput(int nArr[],int nN) { int i; for(i=1;i<=nN;i++) { scanf("%d",&nArr[i]); } } int nGetLnds(int nArr[],int nN) { int nF[MAX]; //表示第i项到最后一项的最长不下降子序列的长度 int nRet,i,j,nTemp; for(i=1;i<=nN;i++) { nF[i]=1; } nRet=1; //当前的最长不下降子序列长度 for(i=nN-1;i>=1;i--) { nTemp=1; //此节点开始的最长不下降子序列长度即:nF[i] for(j=i+1;j<=nN;j++) { if((nArr[i]<=nArr[j])&&(nTemp<nF[j]+1)) { nTemp=nF[j]+1; } } nF[i]=nTemp; if(nRet<nF[i]) { nRet=nF[i]; } } return nRet; } void vOut(int nOut) { printf("%d\n",nOut); }
其次我们来求解【子问题二】
由于最长的子序列可能有多个,我们规定长度相同的子序列按照子序列中元素在原序列中出现的顺序排列,如果相同长度的第一个元素相同(实际上对于不下降子序列问题或者不上升子序列问题,不同的最长子序列中次序位置相同的元素不可能相同!此时只要看第一个元素的位置就可;但对于上升子序列问题或者下降子序列问题,那么次序位置相同的元素可能相同),那么看第二个元素在原序列中的前后位置,如果第二个相同,那可再看第三个元素在原序列中的位置,……,依次类推,我们只要求输出第一个最长的不下降子序列。
参考代码:
#include<iostream> using namespace std; #define MAX 10001 void vInput(int nArr[],int nN); int nGetLnds(int nArr[],int nInd[],int nN,int &nFrom); void vOut(int nArr[],int nInd[],int nOut,int nFrom); int main() { int nNum,nAns,nHead; int nData[MAX],nLinks[MAX]; while(1==scanf("%d",&nNum)) { vInput(nData,nNum); nAns=nGetLnds(nData,nLinks,nNum,nHead); vOut(nData,nLinks,nAns,nHead); } return 0; } void vInput(int nArr[],int nN) { int i; for(i=1;i<=nN;i++) scanf("%d",&nArr[i]); } int nGetLnds(int nArr[],int nInd[],int nN,int &nFrom) { int nF[MAX]; int i,j,nTemp,nIndex,nRet; for(i=1;i<=nN;i++) nF[i]=1; nRet=1;nFrom=nN;nInd[nN]=nN; for(i=nN-1;i>=1;i--) { nTemp=1;nIndex=i; for(j=i+1;j<=nN;j++) { if((nArr[i]<=nArr[j])&&(nTemp<nF[j]+1)) { nTemp=nF[j]+1;nIndex=j; } } nF[i]=nTemp;nInd[i]=nIndex; if(nRet<=nF[i])//注意:这里的=号在计算长度时不会影响! { nRet=nF[i];nFrom=i; } } return nRet; } void vOut(int nArr[],int nInd[],int nOut,int nFrom) { int nTemp,i; printf("%d\n",nOut); nTemp=nFrom; for(i=1;i<=nOut;i++) { if(i==nOut) printf("%d\n",nArr[nTemp]); else printf("%d ",nArr[nTemp]); nTemp=nInd[nTemp]; } }
相关文章推荐
- 最长非降/下降子序列问题(DP)(待续...)
- [dp] Testing the CATCHER 最长下降子序列问题
- C++ 关于最长下降子序列问题
- 【DP】最长不下降子序列问题(二分)
- 【DP】最长不下降子序列问题(二分)
- 洛谷P2766:最长不下降子序列问题
- (2)最长不下降子序列问题____动态规划
- NIOP 1999 导弹问题 最长升降序子序列 DP[小思路]
- POJ 1887 Testing the CATCHER 最长不下降序列(LIS)问题
- 「网络流24题」最长不下降子序列问题
- NYOJ 79 & 17 & 214 单调最长子序列问题(DP)
- 【网络流24题】最长不下降子序列问题
- 最长不下降子序列问题
- hdoj1160 FatMouse's Speed ( STL + 最长下降子序列 /DP)
- 导弹拦截(最长下降子序列 dp)
- DP 求最长不下降序列
- hrbust 哈理工OJ 2010 二等队形【dp】【最长递减子序列问题】
- 最长上升子序列、最长下降子序列的DP算法由O(n^2)到O(nlogn)算法实现及其优化
- 网络流二十四题之六 —— 最长不下降子序列问题(ALIS)
- POJ (dp最长上升子序列问题)