最长不下降子序列 动态规划

一。问题描述

给定一个序列a1 a2 a3 ..... an现要求你从中找到最长的不下降子序列

二。问题分析

该问题可以和之前的max sum问题类比,如果从决策的角度入手,直接引入并定义状态f[i]为“a[i]所在子序列到i的长度”,那我们的决策策略应该就是使得“f[i]最大”,所以基于这个分析我们很容易列出动态转移方程f[i]=max{ f [ j ] } +1 (1<=j<i&&a[j]<=a[i])

代码:

//
//  main.cpp
//  最长不下降子序列
//
//  Created by 张嘉韬 on 16/1/17.
//  Copyright © 2016年 张嘉韬. All rights reserved.
//

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    freopen("/Users/zhangjiatao/Desktop/input.txt","r",stdin);
    int a[500][3],n,max,maxnum,flag,flagnum;
    flag=0,flagnum=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i][0];
        a[i][1]=1;
        a[i][2]=0;
    }
    for(int i=n-1;i>=1;i--)
    {
        max=0,maxnum=0;
        for(int j=i+1;j<=n;j++)
        {
            if(a[j][0]>=a[i][0]&&a[j][1]>max) max=a[j][1],maxnum=j;
        }
        a[i][1]=max+1;
        a[i][2]=maxnum;
        if(a[i][1]>flag) flag=a[i][1],flagnum=i;
    }
    int k=flagnum;
    cout<<a[flagnum][1]<<endl;
    while(a[k][2]!=0)
    {
        cout<<a[k][0]<<" ";
        k=a[k][2];
    }
    cout<<a[k][0]<<endl;
    return 0;
}
小结:从这道题我们应该可以发线一个问题,对于最长不下降子序列,每一个元素都应当“参与”到这个过程中来,也就是说假设出现这种情况

a 1 2 3 4 5 6 4

f  1 2 3 4 5 6 ?

那么这里的f[7]应该选择多少呢,很明显应该是1,首先从直观上是很明显的事,但是随着题目的抽象水平越来越高,有时凭直观也许很难发现这个问题,另一方面,根据f[i]这个状态的定义我们也能推理出来我们,应该把a[i]加入队列

你可能感兴趣的:(最长不下降子序列 动态规划)