动态规划(Dynamic Programming)是是运筹学的一个分支,是求解决策过程最优化的数学方法。 动态规划被用于解决多阶段最优化决策问题。它的基本思路是将待解决的问题划分成多个阶段,每个阶段可能存在多种不同的状态。如果划分阶段后的问题满足最优子结构,则可以用动态规划算法一个阶段一个阶段,一个状态一个状态地解决问题的所有子问题,继而解决原问题。(罗嗦的概念)
动规分为几部分
阶段
阶段的划分是人为的。但是必须满足在一个阶段的任意状态做出任何决策后,得到的新状态都属于之后的阶段。(甚至不能在原阶段停留) 不过实际问题中,有的时候阶段并不是线性的,有的时候你很难描述阶段,但是实际上阶段只是提供了一个解决问题的顺序和设计状态的思路,设计出合理高效的状态才是解决问题的关键。 即:阶段的最大作用是辅助状态设计。
状态
到达某个过程,处于某个状态。一个状态是一个事件,并且包含一切会对决策产生影响的限制条件。
子问题
把一个大的问题化为越来越简单的子问题,通过状态转移方程对大问题求解。子问题与原问题非常相似,或者说根本就是同一个问题,相同的限制条件,相同的最终目的,只是改变了问题的规模,而解决问题需要的方法,也许可以完全仿照原问题。看到这里,你想到了什么?递归!搜索!
决策
决策是一个集合。不同的状态可能有不同的决策集合。但是同一个状态一定有相同的决策集合。
转移
转移用来描述两个子问题之间的关系,A子问题对应的状态进行决策C能到转化为B子问题,称为A→B有C转移。
废话不多说看题(虽然说了不少)
1258:【例9.2】数字金字塔
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 11942 通过数: 6782
【题目描述】
观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。
在上面的样例中,从13到8到26到15到24的路径产生了最大的和86。
【输入】
第一个行包含R(1≤ R≤1000),表示行的数目。
后面每行为这个数字金字塔特定行包含的整数。
所有的被供应的整数是非负的且不大于100。
【输出】
单独的一行,包含那个可能得到的最大的和。
【输入样例】
5 13 11 8 12 7 26 6 14 15 8 12 7 13 24 11
【输出样例】
86
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int a[1001][1001],f[1001][1001];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
cin>>a[i][j];
}
for(int i=n;i>=1;i--)
{
for(int j=1;j<=i;j++)
f[i][j]=max(f[i+1][j],f[i+1][j+1])+a[i][j]; //状态转移方程不难看懂
}
cout<<f[1][1];
}
1259:【例9.3】求最长不下降序列
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 14765 通过数: 4732
【题目描述】
设有由n(1≤n≤200)n(1≤n≤200)个不相同的整数组成的数列,记为:b(1)、b(2)、……、b(n)b(1)、b(2)、……、b(n)若存在i1<i2<i3<…<iei1<i2<i3<…<ie 且有b(i1)≤b(i2)≤…≤b(ie)b(i1)≤b(i2)≤…≤b(ie)则称为长度为e的不下降序列。程序要求,当原数列出之后,求出最长的不下降序列。
例如13,7,9,16,38,24,37,18,44,19,21,22,63,15。例中13,16,18,19,21,22,63就是一个长度为7的不下降序列,同时也有7 ,9,16,18,19,21,22,63组成的长度为8的不下降序列。
【输入】
第一行为n,第二行为用空格隔开的n个整数。
【输出】
第一行为输出最大个数max(形式见样例);
第二行为max个整数形成的不下降序列,答案可能不唯一,输出一种就可以了,本题进行特殊评测。
【输入样例】
14 13 7 9 16 38 24 37 18 44 19 21 22 63 15
【输出样例】
max=8 7 9 16 18 19 21 22 63
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int a[201],f[201],c[201];
int main()
{
int n,maxx=0xc0c0c0c0;
int k;
cin>>n;
for(int i=1;i<=n;i++)
f[i]=1;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=2;i<=n;i++)
for(int j=1;j<i;j++)
{
if(a[i]>=a[j])
if(f[i]<f[j]+1)
f[i]=f[j]+1;
}
for(int i=1;i<=n;i++)
if(f[i]>maxx)
{
maxx=f[i];
k=i;
}
cout<<"max="<<maxx<<endl;
int q=1,m=maxx,ii=k-1;
c[1]=k;
while(m>1)
{
if(f[ii]==m-1&&a[ii]<=a[k])
{
c[++q]=ii;
k=ii;
m--;
}
ii--;
}
for(ii=q;ii>0;ii--)
printf("%d ",a[c[ii]]);
}