AcWing 898. 线性DP——数字三角形

原题链接:

898. 数字三角形 - AcWing题库

题解:

暴搜dfs:

采用暴力搜索需要考虑2^(n-1)条路径,对于本题的1≤n≤500而言肯定会超时。这里附上一个y总总结的根据n的范围判断用什么算法的表

dp:

根据闫氏dp法,对于这种dp问题:

①首先要确定状态表示,但对于状态表示这种东西,其实不是想出来的,而是从经验上得到的,往往是之前做过这种题型然后遇到了类似的题型就有经验了。

对于之前的背包问题,我们用的二维状态f[i][j]表示在考虑前i个物品的情况下背包容量为j时的最优解。而对于这个路线问题,往往采用的状态表示是点的坐标。

②确定状态表示后,我们需要确定由f[i][j]组成的是一个什么样的集合,以及f[i][j]存储的是什么属性(往往是最大值、最小值、个数,本题是最大值) 。那么这是一个什么集合呢?结合题意,这里应该表示从上往下(或者从下往上)走到(i, j)坐标的所有路线的集合。

③接着需要完成状态计算(其实质就是集合划分),很自然地想到,从上往下的话会有两种情况,一种是上层的左侧结点走到本层结点处,另一种是上层的右侧结点走到本层结点处,但是这样子考虑的话对于最左侧或者最右侧的结点,会有越界情况的出现,因此采用从下往上的思路更好。分为两种情况,一种是下层的左侧结点走到本层结点处,另一种是下层的右侧结点走到本层结点处。

因此状态转移方程为:

f[i][j]=max(f[i+1][j], f[i+1][j+1])+w[i][j] 

代码:

暴搜dfs:

你可能觉得从(1, 1)出发是自上向下,需要考虑越界情况,但dfs由于其递归属性,其实是自底向上的,所以不需要考虑越界。

#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 510;
int w[N][N];
int n, res = ~INF;

void dfs(int x, int y, int cur) {
	if (x == n) res = max(cur, res);
	else {
		dfs(x + 1, y, cur + w[x + 1][y]);
		dfs(x + 1, y + 1, cur + w[x + 1][y + 1]);
	}
}

int main() {
	cin >> n;
	for (int i = 1;i <= n;i++)
		for (int j = 1;j <= i;j++) cin >> w[i][j];
	dfs(1, 1, w[1][1]);
	cout << res;
}
dp:
优化前:
#include<bits/stdc++.h>
using namespace std;
const int N = 510;
int f[N][N], w[N][N];
int n;

int main() {
	cin >> n;
	for (int i = 1;i <= n;i++)
		for (int j = 1;j <= i;j++) cin >> w[i][j];
	for (int i = n;i >= 1;i--) f[n][i] = w[n][i];
	for (int i = n - 1;i >= 1;i--)
		for (int j = 1;j <= i;j++)
			f[i][j] = max(f[i + 1][j], f[i + 1][j + 1]) + w[i][j];
	cout << f[1][1];
}
优化后:
#include<bits/stdc++.h>
using namespace std;
const int N = 510;
int f[N][N];
int n;

int main() {
	cin >> n;
	for (int i = 1;i <= n;i++)
		for (int j = 1;j <= i;j++) cin >> f[i][j];
	for (int i = n - 1;i >= 1;i--)
		for (int j = 1;j <= i;j++)
			f[i][j] += max(f[i + 1][j], f[i + 1][j + 1]);
	cout << f[1][1];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值