数字三角形问题

给定一个由n行数字组成的数字三角形,设计一个算法,计算出从三角形的顶至底的一条路径,使该路径经过的数字总和最大。
(0,0)
(1,0) (1,1)
(2,0) (2,1) (2,2)
(3,0) (3,1) (3,2) (3,3)




思路:动态规划
动态方程: sum(i,j) = a(i,j) + max{sum((i+1),j) , sum((i+1),(j+1))} 。
sum(i,j)表示从(i,j)出发时能得到的最大和(包括(i,j)本身的值),a(i,j)表示位置(i,j)的值。
动态方程可解释为:从(i,j)出发有两种决策。如果往下走,则走到(i+1,j)后需要求“从(i+1,j)出发后所能得到的最大和”这一问题,即sum(i+1,j)。
类似的,往右走之后需要求解sum(i+1,j+1)。由于这两个决策中自由选择,所以应选择d(i+1,j)和d(i+1,j+1)中较大的一个。

原问题的解即为:d(0,0)


#include<stdio.h>

int **a;
int **sum;
int n;


//递推计算
int func1(int i,int j)
{
	int x=i,y=j;
	//初始化最底层
	for(j=0;j<n;j++)
		sum[n-1][j]=a[n-1][j];
		
	for(i=n-2;i>=0;i--)//逆序
		for(j=0;j<=i;j++)
			if(sum[i+1][j]>=sum[i+1][j+1])
				sum[i][j] = a[i][j] + sum[i+1][j];
			else
				sum[i][j] = a[i][j] + sum[i+1][j+1];				
	return sum[x][y];
}


//记忆化搜索,为了避免递归计算的重复计算问题,memset(sum,-1,sizeof(sum))。
int func2(int i,int j)
{
	//判断是否记忆标记
	if(sum[i][j]>=0)
		return sum[i][j];
	
	if(i==(n-1))
		return a[i][j];
	else
		if(func2(i+1,j)>=func2(i+1,j+1))
			return a[i][j]+func2(i+1,j);
		else
			return a[i][j]+func2(i+1,j+1);
}

int main()
{
	int i,j;
	
	scanf("%d",&n);//层数

	//数组a,d动态申请空间
	a = new int*[n];
	for(i=0;i<n;i++)
		a[i] = new int[n];
	sum = new int*[n];
	for(i=0;i<n;i++)
		sum[i] = new int[n];
	
	//键入各点的值
	for(i=0;i<n;i++)
		for(j=0;j<=i;j++)
			scanf("%d",&a[i][j]);
	
	

	//逆推计算
	printf("%d\n",func1(0,0));


	//记忆化搜索
	//将sum初始化为-1,做标记
	for(i=0;i<n;i++)
		for(j=0;j<=i;j++)
			sum[i][j]=-1;
	printf("%d\n",func2(0,0));
		

	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值