跳到主要内容

动态规划之二——线性DP入门

2.1 P1115 最大子段和

题目描述

给出一个长度为 nn 的序列 aa,选出其中连续且非空的一段使得这段和最大。

输入格式

第一行是一个整数,表示序列的长度 nn

第二行有 nn 个整数,第 ii 个整数表示序列的第 ii 个数字 aia_i

输出格式

输出一行一个整数表示答案。

输入输出样例 #1

输入 #1
7
2 -4 3 -1 2 -4 3
输出 #1
4

说明/提示

######## 样例 1 解释

选取 [3,5][3, 5] 子段 {3,1,2}\{3, -1, 2\},其和为 44

######## 数据规模与约定

  • 对于 40%40\% 的数据,保证 n2×103n \leq 2 \times 10^3
  • 对于 100%100\% 的数据,保证 1n2×1051 \leq n \leq 2 \times 10^5104ai104-10^4 \leq a_i \leq 10^4

初始思路

最直接的想法是,枚举所有可能的连续子数组,并计算它们的和,然后找出最大的那个。

#include <bits/stdc++.h>
using namespace std;

int main() {
  int n;
  cin >> n;
  int a[n];
  for(int i=0; i<n; i++) cin >> a[i];
  
  int max_sum = INT_MIN;
  for(int i=0; i<n; i++) {
      int current_sum = 0;
      for(int j=i; j<n; j++) {
          current_sum += a[j];
          if(current_sum > max_sum) {
              max_sum = current_sum;
          }
      }
  }
  cout << max_sum << endl;
  return 0;
}

但这个的时间复杂度是 O(n^2),我们需要考虑更高效的做法,比如动态规划.

2.2 P1216 [IOI 1994] 数字三角形 Number Triangles

题目描述

观察下面的数字金字塔。

写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。

数字三角形

在上面的样例中,从 738757 \to 3 \to 8 \to 7 \to 5 的路径产生了最大权值。

输入格式

第一个行一个正整数 rr ,表示行的数目。

后面每行为这个数字金字塔特定行包含的整数。

输出格式

单独的一行,包含那个可能得到的最大的和。

输入输出样例 #1

输入 #1
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出 #1
30

说明/提示

【数据范围】
对于 100%100\% 的数据,1r10001\le r \le 1000,所有输入在 [0,100][0,100] 范围内。

题目翻译来自NOCOW。

USACO Training Section 1.5

IOI1994 Day1T1

题意初步分析
给定数字三角形,从顶部到底部选择路径,每次只能向下或右下移动,求最大路径和。
示例输入(5层):

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

最大路径:7→3→8→7→5,总和30

暴力枚举

  • 路径总数 = 2^(n-1) → 指数级复杂度
  • 画出所有路径树,标出重复计算的子路径

关键提问
"如何避免重复计算相同子路径?能否用记忆化方式存储中间结果?"

2.3 B3637 最长上升子序列

题目描述

这是一个简单的动规板子题,简称LIS(Longest Increasing Subsequence)。

给出一个由 n(n5000)n(n\le 5000) 个不超过 10610^6 的正整数组成的序列。请输出这个序列的最长上升子序列的长度。

最长上升子序列是指,从原序列中按顺序取出一些数字排在一起,这些数字是逐渐增大的。

输入格式

第一行,一个整数 nn,表示序列长度。

第二行有 nn 个整数,表示这个序列。

输出格式

一个整数表示答案。

输入输出样例 #1

输入 #1
6
1 2 4 1 3 4
输出 #1
4

说明/提示

分别取出 11223344 即可。

状态定义
dp[i] 表示以第 i 个元素结尾的最长上升子序列的长度。

举例分析: 序列:[3,1,4,1,5]
以第0个元素结尾:dp[0] = 1(只有3,所以长度是1)
以第1个元素结尾:dp[1] = 1(只有3或1,所以长度还是1)
以第2个元素结尾:dp[2] = dp[1]+ 1 → 2(1和4,最大长度为2)

是不是后续都可以这样推理?
有什么"特殊"情况或需要分类处理?

扩展练习:

  1. 最大子段和
  2. [USACO1.5] [IOI1994]数字三角形 Number Triangles
  3. [NOIP2000 提高组] 方格取数
  4. [CSP-J2020] 方格取数
  5. 最长上升子序列
  6. [NOIP2004 提高组] 合唱队形
  7. [NOIP1999 提高组] 导弹拦截

*学习笔记

暂没有学习笔记,快来抢first blood !