数字三角形(线性dp)-java

线性DP是动态规划问题中的一类问题,指状态之间有线性关系的动态规划问题。


前言

线性DP是动态规划问题中的一类问题,指状态之间有线性关系的动态规划问题。


提示:以下是本篇文章正文内容,下面案例可供参考

一、数字三角形问题

给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。

        7
      3   8
    8   1   0
  2   7   4   4
4   5   2   6   5

二、算法思路

图 1.1样例图

我们引入把数据分为5行,然后按照斜方向算一列进行存储数据。例数字6所在的位置为(5,4)。引入一个二维数组a[i][j]来存储每一个点上的数值。 

我们引入dp数组,dp[i][j]表示所有从起点走到(i,j)的路径的数字之和的最大值

我们以图中的(2,7)的数字7为例,如果要实现到数字7的路径的数字的最大值,那么就是从左上和右上的两种情况中取最大值即:

图1.2样例模拟图 

故dp[i][j]的递推公式为:

dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+a[i][j]

整个dp状态数组的数据如下:

0 0  0  0  0  0 
0 7  0  0  0  0 
0 10 15 0  0  0 
0 18 16 15 0  0 
0 20 25 20 19 0 
0 24 30 27 26 24 

三、使用步骤

1.代码如下(示例):



import java.io.*;
public class 数字三角形 {
    static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

    public static void main(String[] args) throws Exception{
        int n = nextInt();
        int[][] a = new int[510][510];
        int[][] dp = new int[510][510];
        //录入数据
        for(int i = 1;i <= n;i++){
            for(int j = 1;j <= i;j++){
                a[i][j] = nextInt();
            }
        }
        //dp数组初始化
        for (int i = 0; i <= n;i++){
            for(int j = 0;j <= i+1;j++){
                dp[i][j] = Integer.MIN_VALUE;
            }
        }
        //构建dp数组
        dp[1][1] = a[1][1];
        for (int i = 2; i <= n;i++){
            for(int j = 1;j <= i;j++){
                dp[i][j] = a[i][j]+Math.max(dp[i-1][j-1],dp[i-1][j]);
            }
        }
        int res = Integer.MIN_VALUE;
        //dp数组的最后一行表示我们从起点走到最后一行底部的各各最大值,找出其中最大的即可
        for(int j = 1;j <= n;j++){
            res = Math.max(res,dp[n][j]);
        }
        pw.println(res);
        pw.flush();
    }
    public static int nextInt()throws Exception{
        st.nextToken();
        return (int)st.nval;
    }
}

2.读入数据

5
7
3 8
8 1 0 
2 7 4 4
4 5 2 6 5

3.代码运行结果

30

总结

在dp数组的初始化中我们每一行的右边界值必须再往右多初始化一个值和左边界值再往左多初始化,因为左边会有一个左上的点过来,右边会有一个从右上过来的点,而且我们a数组里面的值也有可能是负数,所以初始化是采用Integer.MIN_VALUE。

  • 19
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值