对于能利用动态规划算法解决的问题一般具有以下特征
(1).原问题的最优解一定包含子问题的最优解,即具有最优化子结构。
(2).子问题本质上是和母问题一样的,只是问题的输入规模不一样,可以称之为子问题重叠,这是动态规划解决问题的高效的本质所在,我们可以利用很多子问题具有相同的输入参数这一个性质,来减少计算量。
(3).子问题相互独立。原问题的每个子问题在求最优解时,都是相互独立的,即本子问题的求解和其他平行子问题是没有关联的。当平行子问题解决后,进行原问题求解的时候,才会考虑每个子问题之间的关系,是求最大值还是最小值,还是要做相关的运算得到原问题的最优解。
动态规划算法的基本步骤
(1).找出问题的最优解结构。
(2).递归定义最优解的值。
(3).按自底向上的方式计算最优解的值。
(4).根据计算最优值时得到的信息构造最优解。
下面以租用游艇问题为例,阐述动态规划算法。
问题描述:
长江游艇俱乐部在长江上设置了n个游艇出租站1,2,…,n。游客可在这些游艇出租站租用游艇,并在下游的任何一个游艇出租站归还游艇。游艇出租站i到游艇出租站j之间的租金为r(i,j),1<=i<j<=n。试设计一个算法,计算出从游艇出租站1到游艇出租站n所需的最少租金。
算法设计:
对于给定的游艇出租站i到游艇出租站j之间的租金为r(i,j),1<=i<j<=n,编程计算从游艇出租站1到游艇出租站n所需的最少租金。
数据输入
输入一1个正整数n(n<=200),表示有n个游艇出租站。接下来的n-1行是r(i,j),1<=i<j<=n。
输入样例
3
5 15
输出结果
12
分析
r(i,j)表示从第i站到第j站租用游艇的租金。
c(i,j)表示游艇从第i站出发,到达第j站所有游艇的最少租金。
例如从第1站到第4站的租用方法有1->4;1->2,2->4;1->3,3->4;1-2>,2->3,3->4。
所以c(1,4)=min{r(1,4),r(1,2)+r(2,4),r(1,3)+r(3,4),r(1,2)+r(2,3)+r(3,4)}
由此可以得出递归方程
代码部分:
为了节省空间,直接只使用一个r[200][200]二维数组。
#include <stdio.h>
#include <stdlib.h>
int r[200][200];
void Min(int n)
{
int i,j,t;
int temp;
for(i=n; i>=1; i--)
{
for(j=i; j<=n; j++)
{
if (i==j)r[i][j]=0;
else
{
for(t=i+1; t<j; t++)
{
temp=r[i][t]+r[t][j];
if (temp<=r[i][j])
{
r[i][j]=temp;
}
}
}
}
}
}
int main()
{
int n;
scanf("%d",&n);
int i,j;
for(i=1; i<n; i++)
{
for(j=i+1; j<=n; j++)
{
scanf("%d",&r[i][j]);
}
}
printf("%d",r[1][n]);
return 0;
}