蓝桥杯 数字三角形 简单dp

题目链接:http://oj.ecustacm.cn/problem.php?id=1526

题目分析

第一眼看到这道题,你可能就会想到dp,因为实在是太经典了!但是这道题加了个限制: 向左下走的次数与向右下走的次数相差不能超过1注意:这个限制条件只需要结束时满足,不需要在途中满足)。

完全不会的话

完全不会的同学可以先学下没有限制下是如何解决的:
可以参考这篇文章:https://blog.csdn.net/zwhlxl/article/details/46225947(绝对不是因为我懒得写)

回到本题来

本题中,如果仍然采用dp[i][j]表示到达i行j列的收获的最大值,那么就无法满足限制条件。所以,仅仅靠 i 行 和 j列 这两个维度是无法满足题目要求的。那么该再加入什么样的维度呢?
根据限制条件,可以想到加入一个维度来表示 向左走的次数和向右走的次数的差值

状态定义:

dp[i][j][k] :到达i行j列时,向右走的次数 — 向左走的次数=k的情况下获得的和的最大值

状态转移:

对于一个位置,还是两个方向转移过来:左上和右上,没有左上或者右上的可以看做有一个值为负无穷的左上或右上,这样就必定不会走那里,也就等效于没有,但是我们代码就变得好写了(不用判断是否有左上或右上)

dp[i][j][k]=max(dp[i-1][j][k-1],dp[i-1][j-1][k+1])+arr[i][j] #arr[i][j]为三角形中i行j列的值

初始化:

在这里,我们一开始就知道结果的状态只有dp[0][0][0]。即在最顶上,一步没走的情况下的最大和。

dp[0][0][0]=arr[0][0]

获取结果:

要得到最终答案,就从最后一行满足 限制条件 (-1<=k<=1)的里面去寻找一个最大值即可。

AC代码:

# 数据读取:
n=int(input())
arr=[]
INF=1e9 #定义一个比较大的值(要大于计算过程中可能涉及到的最大值),表示无穷
dp=[[[-INF]*105 for j in range(n)] for i in range(n)]
for i in range(n):
    arr.append(list(map(int,input().split())))
# 初始化:
dp[0][0][0]=arr[0][0]
for i in range(1,n):
    for j in range(i+1):
        for k in range(-50,51):#左右两边之差不可能超过±50
        	#状态转移
            dp[i][j][k]=max(dp[i-1][j][k-1],dp[i-1][j-1][k+1])+arr[i][j]

#获取结果:
ans=-INF
for j in range(n):
    ans=max(ans,dp[n-1][j][-1],dp[n-1][j][0],dp[n-1][j][1])
print(round(ans))

jio得不错的记得点个赞哦(。・∀・)ノ゙

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值