动态规划--最小总和问题

今天又学习了一道使用动态规划解决的问题:数塔最小总和问题

题目是这样的:将正整数排成等边三角形,三角形的底边有n个数,下图给出了n=4的一个例子。从三角形顶点出发通过一系列相邻整数(在图中用圆圈表示),如何使得到达底边时的总和最小?为这个问题设计一个动态规划算法。

n=4时的例子:
动态规划--最小总和问题_第1张图片
我们可以这样考虑这个问题
从第一层开始,最小值为2
第二层为6
那么第三层呢?
第三层=第二层的动态值加上本身

什么意思呢?
因为总层数为三,所以在第二层时,第二层有两种情况,走2+5等于7的路线或者是2+4=6的路线。即有两个动态值,6和7。
那么第三层的候选值就有7+1=8,7+4=11,6+4=10,6+7=13,因此可以选出8为最小值。
那么继续扩展到第四层就有一个问题,中间为4的那个节点,动态值怎么取,这里我们当然要取最小值,即10;

那么对于第四层,上一层的三个候选值就分别为8,10,13
那么到第四层加上自己本身,就可以得出最小值为8+6 = 14;

所以,我们用f【i】【j】来表示,第i层第j个数字的动态累加值。起始时先将所有边缘和非结点的值置无穷大,然后再运算,示例代码如下:

#include 
using namespace std;
int main() 
{
      
 int f[101][101] = {
      0 }; 
 int n = 0; 
 int minData =INT_MAX; 
 cout << "输入三角形底边数目:"; 
 cin >> n; 
 for (int i = 0; i <=n; i++)                      //边缘值置无穷大 
 {
      
  f[i][0] = INT_MAX; 
  f[0][i] = INT_MAX; 
 } 
 cout << "输入各节点的数:"<< endl; 
 for(int i=1;i<=n;i++) 
  for (int j = 1; j <= n; j++) 
  {
      
   if (j <= i) 
    cin >> f[i][j]; 
   else 
    f[i][j] = INT_MAX; 
  } 
 for (int i = 2; i <= n; i++)                             //求各节点动态规划过程中的值 
 {
      
  for (int j = 1; j <=i; j++) 
  {
      
   if (f[i - 1][j - 1] < f[i - 1][j]) //找相对最小值
    f[i][j] += f[i - 1][j - 1]; 
   else if (f[i - 1][j - 1] >f[i - 1][j]) //找相对最小值
    f[i][j] += f[i - 1][j]; 
   else if (f[i - 1][j - 1] ==f[i - 1][j]) //找相对最小值
    f[i][j] += f[i - 1][j]; 
   cout << f[i][j] << " "; 
  } 
  cout << endl; 
 } 
 for (int i = 1; i <= n; i++) 
 {
      
  if (f[n][i] < minData) 
   minData = f[n][i]; 
 } 
 cout << "到达底边时的最小总和为:" << minData << endl; 
 return 0; 
}

中间找相对最小值的步骤可以使用min函数,节省两行代码。该函数包含在头文件里面,这是运行结果,7 6 那一行开始输出的是f【i】【j】的动态值
动态规划--最小总和问题_第2张图片

由于我还没有完全学会怎么用转移方程来表示关系,这里就不列转移方程了,怕误导大家。

对于这题有什么不懂的或者是我做错的地方,欢迎在评论区提出!

你可能感兴趣的:(算法,算法)