前言
动态规划算法解决一些问题,算法的时间复杂度事比较低的。是一种用空间换时间的算法设计思想。
基本结构
F(n)
A[0]=A[1]<-1
for i<-2 to n do
状态转移方程
return A[n]
基本思想
- 动态规划就是用一种类似于表(通常用数组)记录子问题的解,以便保存和以后的检索以从最简单问题的解填起,以自底向上的方式填表。
- 这就保证了,当我们求解一个子问题的时候,所有与子相关的子问题,都可以从表中直接取用,而不必重新计算。
- 动态规划算法策略需要全面考虑不同的情况分别进行决策, 并通过多阶段决策来最终解决问题。
- 在各个阶段采取决策后,会不断决策出新的数据,直到找到最优解。每次决策依赖于当前状态, 又随即引起状态的转移。
- 一个决策序列就是在变化的状态中产生出来的,故有“动态”的含义。所以,这种多阶段决策最优化的解决问题的过程称为动态规划。
基本步骤
- 找出最优解的性质并刻划其结构特征
- 递归的定义最优值
- 以自底向上的方式计算出最优值
- 根据计算最优值时得到的信息构造最优解
优点
- 子问题重叠性质;
- 动态规划用空间换取时间,在有大量重叠子问题的时候其优势才能充分体现出来。
数塔问题
问题
有形如下图的一个数塔,从顶部出发,在每一结点可以选择向左走或是向右走,一直走到底层,要求找出一条路径,使路径上的数值和最大
问题分析
枚举
数塔层数为n,枚举的路径2^(n-1)条
贪心法自上而下
9-15-8-9-10
贪心法自下而上
19 2 10 12 9
口算
9->12->10->18->10
#include<cstdio>
#include <cstring>
const int maxn=110;
int main()
{
int n,m;
int a[maxn][maxn],b[maxn][maxn];
scanf("%d",&n);
while(n--)
{
memset(b,0,sizeof(b));
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
for(int j=1;j<=i;j++)
{
scanf("%d",&a[i][j]);
}
}
for(int i=1;i<=m;i++)
{
b[m][i]=a[m][i];
}
for(int i=m-1;i>0;i--)
{
for(int j=1;j<=i;j++)
{
if(b[i+1][j]>b[i+1][j+1])
b[i][j]=a[i][j]+b[i+1][j];
else
b[i][j]=a[i][j]+b[i+1][j+1];
}
}
printf("%d\n",b[1][1]);
}
return 0;
}
Java实现
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int [][] num = new int [n+2][n+2];
int [][] max = new int [n+2][n+2];
for (int i = 1; i <=n; i++) {
for (int j = 1; j <=i; j++) {
num[i][j]=sc.nextInt();
}
}
for (int i = 1; i <=n; i++) {
for (int j = 1; j <=i; j++) {
//if(j+1>=n+2) continue;
num[i][j]=Math.max(num[i-1][j-1]+num[i][j],num[i-1][j]+num[i][j]);
}
}
int max1 = 0;
for (int i = 1; i <=n+1; i++) {
max1=Math.max(num[n][i], max1);
}
System.out.println(max1);
}
}
优化算法(伪代码)
main()
{int a[50][50][3],i,j,n;
input(n);
for( i=1 ;i<=n;i++)
for (j=1;j<=i;j++){
input(a[i][j][1]);
a[i][j][2]=a[i][j][1];
a[i][j][3]=0;}
for (i=n-1 ; i>=1;i--)
for (j=1 ;j>= i ;j++)
if (a[i+1][j][2]>a[i+1][j+1][2]) {
a[i][j][2]=a[i][j][2]+a[i+1][j][2];
a[i][j][3]=0;}
else {
a[i][j][2]=a[i][j][2]+a[i+1][j+1][2];
a[i][j][3]=1;}
print('max=’,a[1][1][2]);
j=1;
for( i=1 ;i<= n-1;i++){
print(a[i][j][1],‘->’);
j=j+a[i][j][3];
}print (a[n][j][1]);
}
总结
动态规划=贪婪策略+递推(降阶)+存储递推结果。贪婪策略,递推关系都是在“线性”的解决问题。通俗的说动态规划事“带决策的多阶段,多方位的递推算法”。