寒假训练营 动态规划 第1节 笔记

洛谷 U279551 数字三角形

题目描述

给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。

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

输入格式

第一行包含整数 n
,表示数字三角形的层数

接下来 n
行,每行包含若干整数,其中第 i
行表示数字三角形第 i
层包含的整数。

输出格式

输出一个整数,表示最大的路径数字和。

样例 #1

样例输入 #1
5
7
3 8
8 1 0 
2 7 4 4
4 5 2 6 5
样例输出 #1
30

提示

1 ≤ n ≤ 500

−10000 ≤ 三角形中的整数 ≤ 10000

题解

未AC版 40分

数字三角形 
#include<iostream>

using namespace std;

int a[510][510] = {0};
int cnt = 0;	//当前路径
int ans = -1e9;	//最大路径 
int n; 
void dfs(int x , int y) // (x , y)代表坐标,也就是所走路径,x为横坐标,y为纵坐标 
{
	if(x == n)
	{
		if(cnt > ans)
			ans = cnt;
		return;
	}
	
	cnt += a[x+1][y];
	dfs(x+1 , y);
	cnt -= a[x+1][y];
	
	cnt += a[x+1][y+1];
	dfs(x+1 , y+1);
	cnt -= a[x+1][y+1];
}

int main()
{
	cin >> n;
	for(int i = 1 ; i <= n ; i++)
	{
		for(int j = 1 ; j <= i ; j++)
			cin >> a[i][j];
	}
	cnt = a[1][1];
	dfs(1 , 1);
	cout << ans;
	
	return 0;
}

思路:用一个二维数组a[n][n] 来存数字三角形,不难看出每一次移动都是向下或者向右下移动。
我们设计一个自定义递归函数dfs,使得每次移动都向下移动,记录当前路径和,然后回退,再向右下移动,记录当前路径和,然后再回退,递归函数中每一次x = = n ,都代表走完了一条路径。当整个递归函数结束时,代表所有路径都被走完
我们定义了两个变量cnt,ans。用cnt代表某一条路径的长度,用ans储存最大的路径长度每当x = = n 时,比较当前路径长度 cnt 与 最大路径长度 ans 作比较,若 cnt > ans ,则更新 ans 的值等于 cnt 。当整个递归函数结束时,就得到了所有路径中最大的路径长度

不足

采用这种方法,在会出现不必要的计算,以及递归会增加程序运行的时间,当数据量较大时,就有可能出现超时的情况。

AC版

数字三角形 
#include<iostream>

using namespace std;

const int N = 510 , inf = -1e9;
int a[N][N] = {0};
int cnt[N][N];	//用于存储到达a[i][j]时的最大路径cnt[i][j];

int main()
{
	int n;
	cin >> n;
	for(int i = 1 ; i <= n ; i++)
	{
		for(int j = 1 ; j <= i ; j++)
		{
			cin >> a[i][j];
		}
	}
	for(int i = 0 ; i <= n ; i++)
	{
		for(int j = 0 ; j <= n ; j++)
		{
			cnt[i][j] = inf;
		}
	}
	cnt[1][1] = a[1][1];
	for(int i = 2 ; i <= n ; i++)
	{
		for(int j = 1 ; j <= i ; j++)
			cnt[i][j] = max(cnt[i-1][j-1] , cnt[i-1][j]) + a[i][j];
	}
	int ans = inf;	//用ans来存储最大的路程
	for(int j = 1 ; j <= n ; j++) mlans = max(cnt[n][j] , ans);
	cout << ans;
	
	return 0;
 } 

思路: 用一个二维数组cnt[n][n] 来存储到达 a[i][j] 时的最大路径,用 ans 来存储到达第n层时最大路径,用cnt[n][1] ~cnt[n][n] 依次与 ans 进行比较,便能得到最大路径ans。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值