POJ 1163 The Triangle DP

该博客探讨了如何解决POJ 1163问题,即找到一个数字三角形中从顶部到底部的最大数字和。作者提出了三种解决方案:递归、记忆化搜索和循环递推,并解释了如何通过动态规划降低时间复杂度,最终实现AC(Accepted)状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:题目链接

题目描述:

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

(Figure 1)

Figure 1 shows a number triangle. Write a program that calculates the highest sum of numbers passed on a route that starts at the top and ends somewhere on the base. Each step can go either diagonally down to the left or diagonally down to the right. 

题意;图1显示了一个数字三角形。编写一个程序,计算从顶部开始到底部某处的路径上传递的最大数字总和。每个步骤可以沿对角线向下滑动,也可以沿斜向下滑动到右侧。

Your program is to read from standard input. The first line contains one integer N: the number of rows in the triangle. The following N lines describe the data of the triangle. The number of rows in the triangle is > 1 but <= 100. The numbers in the triangle, all integers, are between 0 and 99.

Output

Your program is to write to standard output. The highest sum is written as an integer.

Sample Input

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

Sample Output

30

 

思路1:递归MaxSum(i,j) = max(MaxSum(i+1,j),MaxSum(i+1,j+1))+D[i][j];加上递归出口,if i == n MaxSum(i,j) = D[i][j](说明已经到了最后一行,直接返回即可) (TLE)

 

思路2;

7(1)  

3 (1)   8(1)

8(1)   1(2)  0(1) 

2(1)   7(3)  4(3)  4(1) 

4(1)  5(4)  2(6)  6(4)  5(1)

从图中发现,第一中方法递归重复计算了很多数据,导致时间复杂度升高,为了解决重复计算的问题,采用记忆化搜索,将已经计算过的数据保存至一个数组中,当需要再次使用时,至于要直接拿出来用即可,无需重复计算,if  maxSum[]i[j] != -1,说明没有计算,然后按思路1的过程计算maxSum[i][j],如果已经计算过了,直接return maxSum[i][j].(AC)

思路三:

用循环递推来计算maxSum数组,maxSum[n][i] = D[n][i](i>=1&&i<=n),maxSum[i][j] = max(maxSum[i+1][j],maxSum[i+1][j+1])+ D[i][j] (AC)

  思路一代码:

/*
题目链接:https://vjudge.net/problem/POJ-1163
分类:递归 
*/
#include <iostream>
using namespace std;
const int MAX = 101;
int n;
int D[MAX][MAX];
int MaxSum(int i,int j)
{
	if(i == n) return D[i][j];//已到最后一行 
	else{
		return max(MaxSum(i+1,j),MaxSum(i+1,j+1))+D[i][j];
	} 
}
int main()
{
	cin>>n;
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= i;j++){
			cin>>D[i][j];
		}
	} 
	cout<<MaxSum(1,1)<<endl;
}

思路二代码:

/*
题目链接:https://vjudge.net/problem/POJ-1163
分类:DP 递归 
*/
#include <iostream>
using namespace std;
const int MAX = 101;
int n;
int D[MAX][MAX];
int maxSum[MAX][MAX];
int MaxSum(int i,int j)
{
	if(maxSum[i][j]!=-1) return maxSum[i][j];
	if(i == n) maxSum[i][j] = D[i][j];//已到最后一行 
	else{
		maxSum[i][j] = max(MaxSum(i+1,j),MaxSum(i+1,j+1))+D[i][j];
	} 
	return maxSum[i][j];
}
int main()
{
	cin>>n;
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= i;j++){
			cin>>D[i][j];
			maxSum[i][j] = -1;
		}
	} 
	cout<<MaxSum(1,1)<<endl;
}

思路三代码;

#include <iostream>
const int MAX = 101;
using namespace std;
int n;
int D[MAX][MAX];
int MaxSum[MAX][MAX]; 
int main(){
	cin>>n;
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= i;j++){
			cin>>D[i][j];
		}
	}
	for(int i = 1;i <= n;i++){
		MaxSum[n][i] = D[n][i];
	}
	for(int i = n-1;i >= 1;i--){
		for(int j = 1;j <= i;j++){
			MaxSum[i][j] = max(MaxSum[i+1][j],MaxSum[i+1][j+1]) + D[i][j];
		}
	}
	cout<<MaxSum[1][1]<<endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w͏l͏j͏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值