1.动态规划既多阶段决策问题:将一个问题的求解过程分为多个相互影响相互联系的小过程,在每个小过程中做最优处理,构成一个最优决策序列,从中选取最优决策。
2.动态规划基本模型:
¢ 问题具有多阶段决策的特征。
¢ 每一阶段都有相应的“状态”与之对应,描述状态的量称为“状态变量”。
¢每一阶段都面临一个决策,选择不同的决策将会导致下一阶段不同的状态。
¢每一阶段的最优解问题可以递归地归结为下一阶段各个可能状态的最优解问题,各子问题与原问题具有完全相同的结构。
3.经典例题:最长上升子序列
问题描述: 一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, ..., aN),我们可以得到一些上升的子序列(ai1, ai2, ..., aiK),这里1 <= i1 < i2 <... <iK <= N。
比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1,7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1,3, 5, 8).
你的任务,就是对于给定的序列,求出最长上升子序列的长度
输入数据:输入的第一行是序列的长度N(1 <= N <= 1000)。第二行给出序列中的N 个整数,这些整数的取值范围都在0到10000。
输出要求:最长上升子序列的长度。
分析:求以ak(k=1,2, 3…N)为终点的最长上升子序列的长度”是个好的子问题。
假定MaxLen (k)表示以ak做为“终点”的最长上升子序列的长度,那么:
MaxLen(1) = 1
MaxLen(k) = Max { MaxLen (i):1<i< k 且ai < ak且k≠1} + 1
代码:
#include<bits/stdc++.h>
using namespace std;
int a[100010],maxlen[100010];
//a存储输入的n个数
//maxlen[i]记录以a[i]结尾的最长上升子序列长度
int main()
{
int n,max,ans=-1;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
maxlen[1]=1;
//以a[1]结尾的最长上升子序列长度为1,以maxlen[1]开始递归表示maxlen[i]
for(int i=2;i<=n;i++)
{
max=0;
for(int j=1;j<i;j++)//枚举所有a[i]以前的上升子序列
if(a[j]<a[i])//保证上升
max=max>maxlen[j]?max:maxlen[j];//取最长上升子序列
maxlen[i]=max+1;//求以a[i]结尾的最长上升子序列,并放入最优集maxlen
}
for(int i=1;i<=n;i++)
{
ans=ans>maxlen[i]?ans:maxlen[i];//求最优集中的最优解
}
cout<<ans<<endl;
return 0;
}