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

文章目录

在算法设计中,贪心算法(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 表格)
适用条件 贪心选择性质 + 最优子结构 重叠子问题 + 最优子结构 + 无后效性
通俗比喻 凭直觉走迷宫,选最顺眼的方向,绝不回头 走迷宫时记下每个路口的最优路线,稳扎稳打

分治法

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

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

相关推荐
通信小呆呆20 分钟前
电子战干扰技术:从“蛮力压制”到“精准欺骗”,再到“认知博弈”
算法·通信·isac
老师我太想进步了202643 分钟前
【数据结构-6】算法美学之单链表(1)
数据结构·算法
希望我万事顺遂2 小时前
力扣hot100-滑动窗口最大值
数据结构·算法·leetcode
꧁细听勿语情꧂2 小时前
二叉树余题,排序、直接插入排序、希尔排序
c语言·开发语言·数据结构·算法
是main不是漫3 小时前
【双指针|LeetCode1089 复写零】巧用逆向思路,破解原地覆盖陷阱
数据结构·算法·leetcode
专注仿真12 小时前
知识问答模型用到的算法集详解及代码实例
python·算法·代码·大模型训练·控制算法
罗西的思考13 小时前
【轻量化复刻大模型 / KIMI K3】AttnRes 模块交互式演示
人工智能·算法·机器学习
好悬给我拽开线17 小时前
ZILOT 论文解析
算法
饮水桶_T18 小时前
JAVA IO流笔记
开发语言·数据结构·算法
星夜离尘5619 小时前
MATLAB 离散数据分箱:半开区间、末端点与计数、加权和、平均
算法·matlab