做题笔记 动态规划DP(洛谷P1216 [IOI1994][USACO1.5]数字三角形 Number Triangles)

题目传送门 P1216 [IOI1994][USACO1.5]数字三角形 Number Triangles

这题是很多教材的DP入门题,确实,用它来练习DP对初学者来说十分容易,不过也有一些教材用来做递推的入门题
在这里插入图片描述

思路分析

我们来看题
我看到这题时有两个思路,第一个是递推,第二个是DP
先说递推,递推的话,我们可以倒推,从最底层出发,往上寻找最大路径,a[i][j]即为第i层第j个时的最大值,那么a[1][1]就是我们所要的答案
所以我们可以这样写

#include<iostream>
using namespace std;
int n,a[1001][1001];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=i;j++){
			cin>>a[i][j];    //输入金字塔
		}
	}
	for(int i=n-1;i>=1;i--){   
	//注意要从第n-1层塔开始,因为从下往上选,第a[i][j]个点只能是由a[i+1][j+1]个或第a[i+1][j]往上走到达,i+1最大为n
		for(int j=1;j<=i;j++){ 
			if(a[i+1][j]>=a[i+1][j+1])   //这里就是判断哪条路大了,也可以用iostream库自带的max
				a[i][j]+=a[i+1][j];
			else a[i][j]+=a[i+1][j+1];
		}
	}
	cout<<a[1][1]<<endl;
	return 0;
}

终于写好了代码,然而交上去,我们会发现,只有55分…
于是我开始尝试DP(其实还可以用记忆化搜索的,各位自己尝试一下吧)
DP其实说白了就是倒着递推,我们从上往下推,找最大的路
不过由于上面递推的经验,这里需要优化一下
用一个一维数组f[i]来存放每条路的和,最后比较一下得出最大值
状态转移方程就是 f [j]=max(f[j],f[j-1])+a[i][j];
现在来看代码

#include<iostream>
using namespace std;
int n,a[1001][1001],f[1001],ans;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=i;j++){
			cin>>a[i][j];
		}
	}
	f[1]=a[1][1];  //初始化
	for(int i=2;i<=n;i++){  
		for(int j=i;j>=1;j--){   //f数组是一维的,所以第二层就要倒着循环,原因和01背包的一维数组优化差不多
			f[j]=max(f[j],f[j-1])+a[i][j];}
	}
	for(int i=1;i<=n;i++){
		ans=(ans>f[i])?ans:f[i];   //比较出最大的
	}
	cout<<ans;
	return 0;
}

到这里我们再提交,就可以AC了

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值