动态规划、贪心算法、分治法

文章目录

在算法设计中,贪心算法(Greedy Algorithms)、动态规划与分治法(Divide and Conquer)并列,是最基础、最重要的算法设计思想。

贪心算法

动态规划

小偷背包示例

knapsack是背包的意思。

代码:

java 复制代码
public class Knapsack01 {

    /**
     * 0-1 背包问题求解
     * @param W 背包的总容量
     * @param w 每个物品的重量数组
     * @param v 每个物品的价值数组
     * @return 背包能装下的最大价值
     */
    public static int knapsack(int W, int[] w, int[] v) {
        int n = w.length; // 物品的总个数
        
        // 1. 定义状态数组:dp[i][j] 表示前 i 个物品在容量为 j 时的最大价值
        // 行数是 n+1(包含0个物品的情况),列数是 W+1(包含容量为0的情况)
        int[][] dp = new int[n + 1][W + 1];

        // 2. 遍历物品(相当于填表的行)
        // 从第 1 个物品开始,直到第 n 个物品
        for (int i = 1; i <= n; i++) {
            
            // 3. 遍历背包容量(相当于填表的列)
            // 从容量 0 一直遍历到最大容量 W
            for (int j = 0; j <= W; j++) {
                
                // 核心决策:小偷面对第 i 个物品时的二选一
                if (j < w[i - 1]) {
                    // 情况 A:当前背包容量 j 小于物品重量 w[i-1]
                    // 小偷装不下这个物品,只能放弃。
                    // 此时的最大价值等于【没有这个物品时】的最大价值
                    dp[i][j] = dp[i - 1][j]; 
                } else {
                    // 情况 B:当前背包容量 j 大于等于物品重量 w[i-1]
                    // 小偷可以装下,此时需要比较"装"与"不装"哪个更划算
                    int notTake = dp[i - 1][j]; // 不装:继承上一行的结果
                    int take = dp[i - 1][j - w[i - 1]] + v[i - 1]; // 装:当前物品价值 + 剩余空间的最优解
                    
                    // 取两者中的最大值
                    dp[i][j] = Math.max(notTake, take); 
                }
            }
        }

        // 4. 返回最终结果:表格右下角的值,即前 n 个物品在容量 W 下的最大价值
        return dp[n][W];
    }

    // 测试代码
    public static void main(String[] args) {
        int W = 5; // 背包容量为 5
        int[] weights = {2, 3, 4}; // 物品重量
        int[] values = {3, 4, 5};  // 物品价值

        int maxValue = knapsack(W, weights, values);
        System.out.println("小偷能偷到的最大价值是: " + maxValue);
    }
}

代码与表格的对应关系

1、i对应表格的行(第几个物品)。注意数组下标从0开始,所以第i个物品的重量是wi-1。

2、j对应表格的列(当前的背包容量)。

3、dpij=Math.max(...)就是我们在表格里写下的那个"取最大值"的动作。

动态规划和贪心算法对比
对比维度 贪心算法 (Greedy) 动态规划 (DP)
核心思想 活在当下,只看眼前(局部最优) 统筹全局,步步为营(全局最优)
决策方式 做出选择后绝不后悔(无回溯) 会考察所有可能的子问题,择优保留
是否记笔记 不需要,只记录当前状态 必须记(通过表格/备忘录避免重复计算)
能否保证最优 不一定(取决于问题是否满足贪心性质) 一定能(只要状态转移正确)
运行效率 极高(通常只需排序或单次扫描) 相对较低(通常需要填表,遍历所有子问题)
空间消耗 极低(通常只需几个变量) 较高(需要额外的内存存储 DP 表格)
适用条件 贪心选择性质 + 最优子结构 重叠子问题 + 最优子结构 + 无后效性
通俗比喻 凭直觉走迷宫,选最顺眼的方向,绝不回头 走迷宫时记下每个路口的最优路线,稳扎稳打

分治法

分治法和归并排序经常划到一起。

分治法是核心思想,归并排序是其中一种具体的算法。

相关推荐
lzhdim4 小时前
AI的分类
人工智能·算法·机器学习·分类·数据挖掘
凤凰院凶涛QAQ7 小时前
《Java版数据结构 & 集合类剖析》Map & Set & 反射:“从哈希碰撞到红黑树转换,反射帮你扒开 HashMap 的桶数组看个究竟”
java·数据结构·算法
w_zero_one9 小时前
算法--模拟
java·数据结构·算法
秋天的怀念_David10 小时前
算法一千零一夜 · 第十三夜 幻方,武侠世界里的数学迷宫
java·程序人生·算法
秋天的怀念_David10 小时前
算法一千零一夜 · 第十四夜 幻方与奇妙的二进制
java·程序人生·算法
薛定e的猫咪10 小时前
(ICLR 2020)MAML 靠的不是快速学习,而是特征复用
人工智能·深度学习·学习·算法·机器学习
薛定e的猫咪11 小时前
(ICLR 2026)DF-META:面向 FJSP 的无导数元学习实例自适应调度
人工智能·深度学习·学习·算法·机器学习
小羊没烦恼!12 小时前
异步编程:线程概述及使用
java·开发语言·mysql·算法·c#
wanderist.12 小时前
202609CSP认证P3
算法
云淡风轻~窗明几净13 小时前
角谷猜想最接近严格证明的测试 Version1.1.1
人工智能·算法·机器学习·图论