单调递增最长子序列
基本思想
动态规划法重要的是确定状态与状态转移方程
状态是局部环境下得到的局部解,后项的答案由前面的更小的项决定,前面的更小的项又由更小更小的项决定,直到到达一个边界,这称之为状态转移.如给出一个数组a[11]:
如给出一个数组a[11]:
设状态为当前的最长递增子序列,用F[]数组记录,则dp[0]=1;
a[1]>a[0],dp[1]=dp[0]+1=2;a[2]>a[3],dp[2]=dp[1]+1=3;直到dp[5]=dp[4]+1=6;
重点:那么dp[6]应该从哪里得来?a[6]=11,找到a[i]
从上面的分析中找到规律,即dp[i]的值是前面所有小于a[i]的数组的dp[i]的最大值+1;
*此步骤代码如下:
dp[0]=1;
for(i=1;imax)max=dp[w];
dp[i]=max+1;
}
得到状态转移方程:
最后遍历dp[]数组,其最大值即为最长子序列长度;
#include
#include
const int M=100000;
int a[M],dp[M],L[M];
void found(int max,int N){
int q,w,i=N-1;
for(q=max;q>=1;q--){
for(w=i;w>=0;w--){
if(dp[w]==q){
printf("%d ",a[w]);
break;
}
i=w-1;
}
}
}
int main(){
int N;
while(scanf("%d",&N)!=EOF){
int i,w;
for(i=0;imax)max=dp[w];
dp[i]=max+1;
}
int max=-1;
for(i=0;imax)max=dp[i];
printf("%d\n",max);
found(max,N);
}
}
思考:
题目只是要求最长的长度,如果要你输出最长的最序列呢?
给出代码:
void found(int max,int N){
int q,w,i=N-1;
for(q=max;q>=1;q--){
for(w=i;w>=0;w--){
if(dp[w]==q){
printf("%d ",a[w]);
break;
}
i=w-1;
}
}
}
//大一菜鸟一枚,如有错误还望指正