奇数塔问题

文章讨论了如何使用动态规划方法解决一个数塔问题,其中目标是从顶层到底层找到一条奇数长度的最大路径。通过定义状态转移方程,计算从每个节点出发的奇偶长度路径的最大值。
摘要由CSDN通过智能技术生成

问题描述

有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,最终答案必须在最后一行,且为奇数,问答案最大是多少?

分析

考虑用 dp 来做。

状态:

d p i , j , 0 dp_{i,j,0} dpi,j,0 为走到点 i , j i,j i,j 的偶数长度最大路径, d p i , j , 1 dp_{i,j,1} dpi,j,1 为走到点 i , j i,j i,j 的奇数长度最大路径。

状态转移方程:

  • 如果 a i , j a_{i,j} ai,j 是偶数: d p i , j , 1 = max ⁡ ( d p i + 1 , j , 1 , d p i + 1 , j + 1 , 1 ) + a i , j dp_{i,j,1} = \max(dp_{i+1,j,1},dp_{i+1,j+1,1})+a_{i,j} dpi,j,1=max(dpi+1,j,1,dpi+1,j+1,1)+ai,j d p i , j , 0 = max ⁡ ( d p i + 1 , j , 0 , d p i + 1 , j + 1 , 0 ) + a i , j dp_{i,j,0} = \max(dp_{i+1,j,0},dp_{i+1,j+1,0})+a_{i,j} dpi,j,0=max(dpi+1,j,0,dpi+1,j+1,0)+ai,j
  • 如果 a i , j a_{i,j} ai,j 是奇数: d p i , j , 1 = max ⁡ ( d p i + 1 , j , 0 , d p i + 1 , j + 1 , 0 ) + a i , j dp_{i,j,1} = \max(dp_{i+1,j,0},dp_{i+1,j+1,0})+a_{i,j} dpi,j,1=max(dpi+1,j,0,dpi+1,j+1,0)+ai,j d p i , j , 0 = max ⁡ ( d p i + 1 , j , 1 , d p i + 1 , j + 1 , 1 ) + a i , j dp_{i,j,0} = \max(dp_{i+1,j,1},dp_{i+1,j+1,1})+a_{i,j} dpi,j,0=max(dpi+1,j,1,dpi+1,j+1,1)+ai,j

初始状态

d p i , j , 0 = d p i , j , 1 = ∞ dp_{i,j,0}=dp_{i,j,1}=\infty dpi,j,0=dpi,j,1=

  • 如果 a n , i a_{n,i} an,i 是偶数 d p n , i , 0 = a n , i , d p n , i , 1 = 0 dp_{n,i,0} = a_{n,i},dp_{n,i,1}=0 dpn,i,0=an,i,dpn,i,1=0
  • 如果 a n , i a_{n,i} an,i 是奇数 d p n , i , 1 = a n , i , d p n , i , 0 = 0 dp_{n,i,1} = a_{n,i},dp_{n,i,0}=0 dpn,i,1=an,i,dpn,i,0=0

答案输出 d p 1 , 1 , 1 dp_{1,1,1} dp1,1,1 即可。

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 105;
int n, a[N][N], dp[N][N][2];

int main(){
	cin >> n;
	for(int i = 1; i <= n; i ++){
		for(int j = 1; j <= i; j ++){
			cin >> a[i][j];
			dp[i][j][0] = dp[i][j][1] = -1e9;
		}
	}
	for(int i = 1; i <= n; i ++){
		if(a[n][i] % 2 == 0){
			dp[n][i][0] = a[n][i];
			dp[n][i][1] = 0;
		}else{
			dp[n][i][1] = a[n][i];
			dp[n][i][0] = 0;
		}
	}
	for(int i = n - 1; i >= 1; i --){
		for(int j = 1; j <= i; j ++){
			if(a[i][j] % 2 == 0){//偶数 
				dp[i][j][1] = max(dp[i + 1][j][1], dp[i + 1][j + 1][1]) + a[i][j];
				dp[i][j][0] = max(dp[i + 1][j][0], dp[i + 1][j + 1][0]) + a[i][j];
			}else{//奇数 
				dp[i][j][1] = max(dp[i + 1][j][0], dp[i + 1][j + 1][0]) + a[i][j];
				dp[i][j][0] = max(dp[i + 1][j][1], dp[i + 1][j + 1][1]) + a[i][j];
			}
		}
	}
	cout << dp[1][1][1];
	return 0;
}
  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值