动态规划算法的基本要素
最优子结构性质
重子叠问题性质
动态规划算法的设计步骤
找出最优解的性质,刻画其结构特征
递归定义其最优值
以自顶向上的方式计算最优值
根据计算最优值时得到的信息构造最优解
举例
矩阵连乘问题
在多个矩阵相乘的问题中,找出乘法次数最少的解法
例如A1*A2*A3 设三个矩阵的维数为10*100,100*5,5*50
第一种加括号的方式是(A1*A2)*A3,矩阵数乘次数为10*100*5+10*5*50=7500;
第二种加括号的方式为A1*(A2*A3),矩阵数乘次数为100*5*50+10*100*50=75000;
由此我们需要算法来找出最优解决方案
0 | A1——A2 | A1——A3 | A1——A4 |
| 0 | A2——A3 | A2——A4 |
|
| 0 | A3——A4 |
|
|
| 0 |
以四个矩阵相乘为例,我们定义一个二维数组,数组行列长度为矩阵个数,数组的元素所在第i行,第j列,这个元素的数值就表示从第i个矩阵到第J矩阵所用的最少数乘次数。我们选取半三角。
我们先定义对角线上的元素为0,因为他们表示本身到本身的数乘次数,按照四条箭头的方向依次确定所在元素数值,这样下一条箭头利用上一条箭头的最优解能够顺利的求解出元素数值,以A1——A4为例,我们只需利用循环,从A1开始,一直到A4结束(不包括),我们在A1——A4之间中断,在A2,A3出中断,在A2出中断,A1——A2+A3——A4+(A1——A2合并的数组乘以A3——A4合并的数组相乘所需要的数乘次数),这样我们就可以利用上一条箭头为我们求出的最优解(A1——A2)和(A3——A4)。
#include<iostream>
#include<random>
#include<time.h>
using namespace std;
const int num=10; //矩阵个数
int main()
{
srand((unsigned)time(NULL));
int A[num][2]={0}; //矩阵数组 记录维数
int temp[num][num]; //记录半三角形
int i=0,j=0,r=0,k=0;
for(i=0;i<num;i++)
{
temp[i][i]=0;
}
A[0][0]=((double)rand()/RAND_MAX)*20+20;
A[0][1]=((double)rand()/RAND_MAX)*20+20;
for(i=1;i<num;i++)
{
A[i][0]=A[i-1][1];
A[i][1]=((double)rand()/RAND_MAX)*20+20;
}
for(i=0;i<num;i++)
{
r=0;
for(j=i+1;j<num;j++)
{
int min=(numeric_limits<int>::max)();
for(k=r;k<j;k++)
{
min=min<(temp[r][k]+temp[k+1][j]+A[r][0]*A[k][1]*A[j][1])?min:(temp[r][k]+temp[k+1][j]+A[r][0]*A[k][1]*A[j][1]);
}
temp[r][j]=min;
r++;
}
}
for(i=0;i<num;i++)
{
for(j=i+1;j<num;j++)
{
cout<<temp[i][j]<<" ";
}
cout<<endl;
}
return 0;
}