线性dp(数字三角形)

24 篇文章 12 订阅

原题链接:898. 数字三角形 - AcWing题库

按道理来说,线性dp的问题基本都能用暴力解出来,dfs+记录,我们基本能解决所有线性dp问题,但是,博主作为一个备考蓝桥杯的人,暴力骗分一定要会,同时也要会正确的做题方法;

所以这里也呼吁和我一样的菜鸟新手学会多种解法,至少对于这种不是ACM赛制的题,要学会:不会也要骗一点分;

废话多说了,让我们来看题,直接分析,根据闫氏动态规划分析,我们这里先分析状态表示,因为要我们查找权重最大的路径,而且输入也给的很清晰,直接开二维数组存储,i表示第i行,j表示j列,这样可以存储权重和位置;

我们用arr数组存储权重,用dist存储到达当前点的最大权重路径

那么分析完成,如何表示状态转移呢?

看:

 因为这道题给的很巧妙,所以我们的存储也有技巧,这样的话,因为我们的dist数组存储的是到这个点的时候,最大的权重路径,而这个点可以被下面的两个使用。

具体的求法:

 某个点的最大权重路径由这个点上面的点和上面左边的点决定,我们只需要取其中的最大值即可

具体代码:

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N=510,INF=1e9;
int arr[N][N];
int dist[N][N];

int main()
{
	int n;
	cin>>n;
	
	for(int i=1;i<=n;i++)
		for(int j=1;j<=i;j++)
			cin>>arr[i][j];//正常存储 
			
		
	
	for(int i=0;i<=n;i++)
		for(int j=0;j<=n;j++)
			dist[i][j]=-INF;//我们需要考虑负权边,如果出现负权边,就会出现有一些点
			                //遍历到了0,而没有另一个点大,从而使答案错误 
	
	dist[1][1]=arr[1][1];//加不加都可以,不加的话下面从i=1遍历 
	
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<=i;j++)
		{
			dist[i][j]=max(dist[i-1][j]+arr[i][j],dist[i-1][j-1]+arr[i][j]);//取大值存储 
//			cout<<dist[i][j]<<' '; 
		}
//		cout<<endl;
	}
	int max=-INF;
	
	for(int i=1;i<=n;i++) 
	    if(dist[n][i]>max)
	        max=dist[n][i];//要的是到达底边的所有路中的最大值,所以需要遍历一遍 
	        
	cout<<max;//输出 
 } 

负权边情况:

 如果不赋值为负无穷值,那么根据我们的分析,我们的dist数组应该是这样:

 实际上,这是错误的,因为i=2,j=1时,我们只有一个上点,但是分析的时候会把-6左边的零算进去,结果当然是0>-6,所以会出现路径为-6的情况,如果赋值为无穷大就不会出现这种情况。

至此,完结撒花。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值