前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DP专题 | 数字三角形 - POJ 1163

DP专题 | 数字三角形 - POJ 1163

作者头像
ACM算法日常
发布2019-05-31 17:30:05
3320
发布2019-05-31 17:30:05
举报
文章被收录于专栏:ACM算法日常

从本篇开始,准备做一系列的专题讲解,主要参考《算法竞赛入门经典》、《算法竞赛进阶指南》两本书。主要是为了能够更加系统的讲解各个知识点,这两本书已经讲得很好了,建议准备ACM学习以及想深入学习算法的同学购买。

每一个专题都会持续比较久的时间,就比如拿动态规划DP来说,种类非常多,从浅入深可以说是一次深潜,刚开始可能还好,后面会比较困难。限于本人水平有限,我能潜多深,就带大家看多深的风光

~

另外本号的更新频率一般是一周2-3篇,关注本号的童鞋请耐心一点哈。

来看题:

The Triangle

Description

代码语言:javascript
复制
7
3   8
8   1   0
2   7   4   4
4   5   2   6   5

(Figure 1)

Figure 1 shows a number triangle. Write a program that calculates the highest sum of numbers passed on a route that starts at the top and ends somewhere on the base. Each step can go either diagonally down to the left or diagonally down to the right.

Input

Your program is to read from standard input. The first line contains one integer N: the number of rows in the triangle. The following N lines describe the data of the triangle. The number of rows in the triangle is > 1 but <= 100. The numbers in the triangle, all integers, are between 0 and 99.

Output

Your program is to write to standard output. The highest sum is written as an integer.

Sample Input

代码语言:javascript
复制
5
7
3 8
8 1 0 
2 7 4 4
4 5 2 6 5

Sample Output

代码语言:javascript
复制
30

这是DP的入门经典题目,思路的关键是针对位置[i][j]进行状态转移,dp[i][j]表示从第一行走到第i行第j列的最大和。

动态规划里面有很多问题的dp都是以位置i开始或者结束,比如下一篇要讲得LIS问题,不过本题是一个二维的表示。

本题用递推的方式就已经很好实现了,建议不熟的同学再尝试递归的方法。

状态转移方程:

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

A[i][j]是当前位置的值,加上上一行相邻的两个值的较大值,保证了最优子结构。

注意j-1小于0的特殊处理。

时间复杂度:dp的状态总数*决策复杂度,这里是二维的,状态总数也就是i*j,决策只有2中决策。总复杂度O(n2)。

进阶的书里面和本题解法一致,算法竞赛入门里面是从d[i+1][j+1]到d[i][j],思路恰好是逆序的,都可以看看。

最重要的是找到转移方程和边界。

源代码:G++

代码语言:javascript
复制
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <set>
#include <vector>
#include <string>
#include <string.h>
using namespace std;

#ifdef __MSYS__
#define printfd printf
#else
#define printfd
#endif

int main() {
#ifdef __MSYS__
    freopen("test.txt", "r", stdin);
#endif
    int dp[100][100] = {0};
    int a[100][100] = {0};

    int n;
    scanf("%d", &n);

    for(int i=0; i<n; ++i){
        for(int j=0; j<i+1; ++j){
            scanf("%d", &a[i][j]);
        }
    }

    dp[0][0] = a[0][0];
    for(int i=1; i<n; ++i){
        for(int j=0; j<i+1; ++j){
            if(j-1>=0){
                dp[i][j] = a[i][j] + std::max(dp[i-1][j], dp[i-1][j-1]);
            }else{
                dp[i][j] = a[i][j] + dp[i-1][j];
            }
            printfd("%d %d %d\n", i, j, dp[i][j]);
        }
    }

    int m=0;
    for(int j=0; j<n; ++j){
        m = std::max(dp[n-1][j], m);
    }
    printf("%d\n", m);

    return 0;
}

PS~这里我用宏控制了printfd,只有在我的msys环境下才会生效,这样就可以不用改代码直接提交poj评测系统了。

温馨提示

如果你喜欢本文,请分享到朋友圈,想要获得更多信息,请关注ACM算法日常

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-05-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ACM算法日常 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档