「学习笔记」动态规划的引入

一.什么是动态规划

动态规划是一种重要的思维方法,通过利用已有的子问题信息高效求出当前问题的最优解。

由于动态规划并不是某种具体的算法,而是一种解决特定问题的方法,因此它会出现在各式各样的数据结构中,与之相关的题目种类也更为繁杂。

二.动态规划基础

一般的,对于解决动态规划的题目,有以下三个步骤:

  • 1.根据题目设计状态,初始化状态。
  • 2.根据状态,推导转移方程。(也就是考虑如何从 \(i-1\) 转移到 \(i\)
  • 3.确定最优解,求出答案。

而动态规划与贪心算法本质上的区别在于:贪心算法算出的是局部最优解,而动态规划算出的是全局最优解。所以我们要认真读题,避免判断错误。

三.基本例题入门

  • P1216 [USACO1.5][IOI1994]数字三角形 Number Triangles

    读题,按照上文分 \(3\) 步:
    • 1.设立状态: \(dp_{i,j}\) 表示从起点到点 \(i,j\) 的最大价值,初始化 \(dp_{1,1}=a_{1,1}\)
    • 2.推导转移方程:发现当前的 \(dp_{i,j}\) 有两条路可以得到:从点 \(i-1,j-1\) 或点 \(i-1,j\),也就是当前点上一层的两个点。于是转移方程为 \(dp_{i,j}=\text{max}(dp_{i-1,j},dp_{i-1,j-1})+a_{i,j}\)
    • 3.确定最优解:题目要求求到达最底层所获得的最大值。根据我们设计的状态,也就是求 \(\text{max}(dp_{r,i})\)
      代码如下:
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1e3 + 7;
    int dp[N][N], n, a[N][N];
    int main () {
    	cin >> n;
    	for (int i = 1; i <= n; i ++) {
    		for (int j = 1; j <= i; j ++) {
    			cin >> a[i][j];
    		}
    	}
    	for (int i = 1; i <= n; i ++) {
    		for (int j = 1; j <= i; j ++) {
    			dp[i][j] = max (dp[i - 1][j], dp[i - 1][j - 1]) + a[i][j];
    		}
    	}
    	int ans = 0;
    	for (int i = 1; i <= n; i ++) {
    		ans = max (ans, dp[n][i]);
    	}
    	cout << ans;
    	return 0;
    } 
    
posted @ 2022-02-19 12:00  cyhyyds  阅读(49)  评论(0编辑  收藏  举报