一些学习笔记,仅作本人记录之用

比如下面这道题就是个经典的动态规划题目:

tower.jpg

从顶点出发走到最底层,每步只能走到下面相邻的节点,经过的节点之和最大是多少?

可以观察到一直贪心的走下去得到的结果是不正确的,假如知道每个顶点的最优解,我们就可以的出最终答案。

假设第 i 行的第 j 个元素为止的最优解为 f[ i ] [ j ],可以想到 f[ i ] [ j ]只和 f[ i - 1 ] [ j ], f[ i - 1 ] [ j - 1]  有关;就是说第 i 行的解会跟 i -1 行的一个或两个元素有关;

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 100;
// 下面这个函数实现的是更新最大值,o赋值为o和x的最大值
template <class T>
void updateMax(T& o, const T& x) {
    o = (o > x) ? o : x;
}

// f数组为动态规划的状态数组
// num数组为读入的数塔
// n为读入的数塔高度
int f[N][N], num[N][N], n;

int main() {
    // 读入n和数塔数组num
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= i; ++j) {
            scanf("%d", &num[i][j]);
        }
    }

    //在这里实现动态规划算法逻辑
    for (int i=1; i<=n; i++){
        for (int j=1; j<=i; j++){
            updateMax(f[i][j], max(f[i - 1][j], f[i - 1][j - 1])+ num[i][j]);
        }
    }

    // 定义最终结果变量result,因为是计算最大值,所以初始化为0
    int result = 0;
    for (int i = 1; i <= n; ++i) {
        //在这里实现更新最终结果的逻辑
        updateMax(result, f[n][i]);
    }
    // 输出最终最大权值和result
    printf("%d\n", result);
    return 0;
}








最长上升子序列 (Longest Increasing Subsequence, 常简称为 LIS) 是动态规划解决的一个经典问题。

我们先讲一下子序列是什么。一个数组的子序列就是从里面选出一些元素,并将他们保持原有的先后顺序排列。比如[1, 2, 3, 4, 5]的子序列有[1, 3, 5]、[3, 4],而[1, 5, 3]则不是这个数组的子序列。

这里多介绍一下,还有一个容易与子序列混淆的概念:子串。子串是指从一个数组中选出连续的一个或多个元素,并且保持他们原有的顺序。子串一定是子序列,比如前面的子序列[3, 4]就是子串,但[1, 3, 5]不是子串,因为这三个元素在原数组中并不是连续的。

一句话总结他们的区别,就是子序列可以不连续,而子串必须连续。

上 升子序列是指子序列Ai中满足 A1 < A2 < ... < An,也就是后面的元素一定比前面的元素大,比如(1, 3, 5)是上升子序列,(1, 3, 3)和(1, 4, 3)都不是。现在来跟我一起解决最长上升子序列的问题吧!(o・・o)/


输入格式:

第一行一个整数n(1 ≤ n ≤ 100),表示序列的长度。

第二行 n 个整数,表示序列中的每个元素。

输出格式:

输出只有一行,为最长上升子序列的长度。

样例输入:

5

1 5 2 3 4


样例输出:

4


还记得上一道数塔问题我们怎么解决的么?我们首先要把问题拆分成很多子问题。对于这道题来说,我们分解为这样的N个子问题:求解最后一个元素为原数组中第 i (1 ≤ i ≤ n)个元素的最长上升子序列的长度。

如果我们把N个问题都计算出来了,那么最终结果就从所有子问题中选出一个最大值是不是就可以啦?


#include <iostream>
#include <cstdio>
using namespace std;
int n, dp[101], num[101], result = 0;
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &num[i]);
    }
    // 在下面实现动态规划的核心代码
    for (int i=1; i<=n; i++){
        dp[i] = 1;
        for (int j=1; j<i; j++){
            if (num[j] < num[i]){
                dp[i] = max(dp[j] + 1, dp[i]);
            }
        }
        result = max(result, dp[i]);
    }
 
    printf("%d\n", result);
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值