码迷,mamicode.com
首页 > 其他好文 > 详细

动态规划--数字三角形问题

时间:2015-06-24 07:03:13      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:

1. 问题描述

 

有一个像这样的数字三角形:
         

                    7
      3 8
     8 1 0
    2 7 4 4
   4 5 2 6 5

从顶点开始,每个数字向下层走只能有左下和右下两个方向,求出到达最后一行时最大的路径之和。

Input 
第1 行是数字三角形的行数n,1<= n <=100。

接下来n行是数字三角形各行中的数字。所有数字在0---99之间。

比如Input是:

5

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

则output是30。

 

2. 问题求解

 

这是一个典型的动态规划求解问题,因为它符合动态规划所能解决的问题的性质:

最优子结构性质

子问题重叠性

看到这个题目,很容易想起多段图的那个题目,其实道理真的是一样的,唯一的区别就是:一个是从一些顶点到一个终点求最小值;一个是一个起点到一些点求最大值。

所以状态和转移方程都可以模仿多段图的解法:

\[f(i,j) = \max \{ f(i - 1,j - 1),f(i - 1,j)\}  + {C_{ij}}\]

其中i表示该点所在三角形的行数(行数从0开始算),j表示该点所在某行的第几个,也就是列数(列数从0开始计算)。

注意:转移方程中的i,j在代码计算的时候不能越界。所以每一行的两端的数字的f函数要单独计算,只有一种决策才能到达它们。

 

3. 代码实现

 

#define MAX 100
#define getMax(x,y) (x>y ? x : y)
#include <stdio.h>

void main(void)
{
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);

	//初始化数组的元素全部为0
	int path[MAX][MAX] = {0};
	int dist[MAX][MAX] = {0};

	//为三角形赋值
	int i = 0;
	int j = 0;
	int n = 0;	//三角形的行数
	scanf("%d", &n);

	for(i= 0; i < n; i++)
	{
		for(j = 0; j <= i; j++)
		{
			scanf("%d", &path[i][j]);
		}
	}//for

	//为了防止转移方程越界,每行的开头和结尾首先算出最长路径
	dist[0][0] = path[0][0];
	for(i = 1; i < n; i++)
	{
		dist[i][0] = dist[i-1][0] + path[i][0];
	}//for

	for(i = 1; i < n; i++)
	{
		dist[i][i] = dist[i-1][i-1] + path[i][i];
	}

	//计算出中间每个节点的最长路径
	for(i = 2; i < n; i++)
	{
		for(j = 1; j < i; j++)
		{
			dist[i][j] = getMax(dist[i-1][j-1], dist[i-1][j]) + path[i][j];
		}
	}

	//找到最长的路径
	int maxSum = 0;
	for(j = 0; j < n; j++)
	{
		if(maxSum < dist[n-1][j])
		{
			maxSum = dist[n-1][j];
		}
	}//for

	printf("%d", maxSum);


	fclose(stdin);
	fclose(stdout);
	return;
}

  测试数据:

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

 

动态规划--数字三角形问题

标签:

原文地址:http://www.cnblogs.com/stemon/p/4596701.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!