标签搜索

动态规划

爱做梦的月亮
2022-08-23 / 0 评论 / 236 阅读 / 615 个汉字 / 正在检测是否收录...

经典数塔问题

  有一金字塔形数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?

  输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数,且所有的整数均在区间[0,99]内。

输入样例

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

输出样例

30

动态规划代码

#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int f[N][N], dp[N][N];
int main(){
    int C, n;
    cin >> C;
    while(C--) {
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++){
            for(int j = 1; j <= i; j ++){
                scanf("%d", &f[i][j]);
            }
        }
        for(int j = 1; j <= n; j ++)
            dp[n][j] = f[n][j];
        for(int i = n - 1; i >= 1; i --){
            for(int j = 1; j <= i; j ++){
                dp[i][j] = max(dp[i + 1][j], dp[i + 1][j + 1]) + f[i][j];
            }
        }
        printf("%d\n", dp[1][1]);
    }
 
    return 0;
}

分治与动态规划

  分治与动态规划都是将问题分解成子问题,然后合并子问题的解得出原问题的解。不同的是,分治分解的子问题是不重叠的(如快速排序将问题分为处理左序列与右序列),而动态规划问题相反。同时,动态规划一定解决的是最优化问题,而分治不一定。

贪心与动态规划

  它们都是将问题变成处理子问题,都要求原问题拥有最优子结构。二者的区别在于,贪心类似于“自顶向下”,但是是通过一种最优策略直接选择一个子问题求解,其它子问题则直接舍弃。这就是说,它总是在上一步选择的基础上继续选择,整个过程是单链的。显然,这种“最优选择策略”的正确性需要进一步归纳证明。比如数塔问题,贪心法会从第一层开始,选择下面两数更大的那个一直走下去,显然这并不一定能得到最优解。而动态规划不管是自顶向下还是自底向上,本质上都是从边界开始得到目标问题的最优解。也就是说,它会考虑完所有子问题,并选择继承能得到最优结果的那个,对于暂时没被继承的子问题也不会直接舍弃——由于重叠子问题的存在,后期可能会再次考虑它们,因此它们仍然有机会成为全局最优的一部分。

  贪心是一种壮士断腕的决策——只要进行的选择就一直走下去不后悔;动态规划则是动态地考虑问题,看谁能笑到最后——局部的领先不代表全局的领先。

0

评论 (0)

取消