贪心(基础算法)--- 货仓选址

本文介绍了如何通过贪心策略解决货仓选址问题,将货仓建在所有商店的中位数位置,使得所有商店到货仓的距离之和最小。作者给出了Java代码示例,展示了如何利用数组排序实现这一算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

104. 货仓选址

image-20240304130039154

思路

(贪心)O(nlogn)

题目要求的是n个商店与货仓的距离之和s最小,那么我们可以先来看看当商店如何选择才能使得s最小? 假设区间[a,b]的距离是n

  • 把A[0]~A[N-1]排序,设货仓在X坐标处,X左侧的商店有P家,右侧的商店有Q家。

    image-20240304131424679

  • 若P < Q,则每把仓库的选址向右移动1单位距离,距离之和就会变少Q - P.同理,若P > Q,则仓库的选址向左移动会使距离之和变小。当P==Q时为最优解。

  • 因此仓库应该建在中位数处,先把A进行排序,我们数组从0开始,

    当N为奇数时,货仓建在A[N /2]处,

    当N为偶数时,仓库建在A[(N -1)/2]~A[N / 2]之间处都可。

得出结论:我们将货场建在A[N /2]即可

Java代码

import java.util.*;
​
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] q = new int[n];
        for(int i = 0; i < n; i ++){
            q[i] = sc.nextInt();
        }
        Arrays.sort(q, 0, n);
        int mid = n / 2;
        int s = 0;
        for(int i = 0; i < n; i++ ) {
            s += i <= mid ? q[mid] - q[i] : q[i] - q[mid];
        }
        System.out.println(s);
    }
}
<think>好的,我现在需要回答用户关于贪心算法在采花生问题中的应用的问题。首先,我需要回忆一下采花生问题的具体内容。采花生问题通常是指在一个网格中,每个格子有一定数量的花生,一个人从左上角出发,每次只能向右或向下移动,最终到达右下角,要求收集到最多的花生。这应该是一个动态规划问题,但用户提到的是贪心算法,可能需要先理清楚两者的区别。 用户可能混淆了贪心算法和动态规划的应用场景。贪心算法通常每一步都选择当前最优,但可能无法得到全局最优解。而像采花生这样的问题,由于路径的选择会影响后续的结果,需要全局考虑,因此更适合用动态规划来解决。例如,每个位置的最大花生数只能由左边或上边的位置决定,因此需要递推计算每个位置的值。 接下来,我需要确认用户提供的引用内容是否有相关的信息。查看用户给出的引用,引用[1]提到了动态规划的相关内容,包括摘花生问题的题解,这可能与用户的问题相关。引用[4]中的示例测试样例可能涉及到类似的问题,但可能不是直接相关。 用户要求示例代码和解题思路,因此我需要先解释为什么贪心算法在这里不适用,然后转而介绍动态规划的解法。同时,需要提供代码示例,可能参考引用中的信息,比如引用[1]中的摘花生题目代码题解部分。 需要注意用户的引用中的摘花生问题可能正是用户所说的采花生问题,所以需要结合引用[1]的内容来回答。根据动态规划的思路,每个位置的最大花生数等于其左边或上边最大值加上当前格子的花生数。代码实现通常使用二维数组来存储中间状态,逐步填充数组,最终右下角的值即为答案。 可能用户误以为这个问题可以用贪心算法解决,但实际上正确的解法是动态规划。因此,在回答时需要指出这一点,并解释贪心算法在此场景中的局限性,例如贪心每次选择当前最大花生路径可能会导致错过全局更优的路径。 最后,生成相关问题时要围绕贪心算法和动态规划的区别,以及采花生问题的其他解法或变体来提问。</think>### 贪心算法在采花生问题中的应用分析 采花生问题的典型场景是:给定一个$m \times n$的网格,每个格子有若干花生,从左上角出发,只能向右或向下移动,最终到达右下角,求能收集的最大花生数。**此问题需用动态规划而非贪心算法解决**,原因如下: 1. **贪心算法的局限性** 贪心算法每一步选择当前最优(如向右或向下中花生更多的方向),但局部最优无法保证全局最优。例如: $$ \begin{matrix} 100 & 1 & 1 \\ 1 & 1 & 100 \end{matrix} $$ 若第一步贪心选择向右(100→1),则无法到达右下角的100;而动态规划会提前计算所有路径。 2. **动态规划的正确性** 定义状态$dp[i][j]$表示到达$(i,j)$时的最大花生数,状态转移方程为: $$ dp[i][j] = \max(dp[i-1][j], dp[i][j-1]) + grid[i][j] $$ 通过递推计算所有位置,最终$dp[m-1][n-1]$即为答案。 --- ### 动态规划实现代码(Python示例) ```python def max_peanuts(grid): m, n = len(grid), len(grid[0]) dp = [[0] * n for _ in range(m)] dp[0][0] = grid[0][0] # 初始化第一行和第一列 for i in range(1, m): dp[i][0] = dp[i-1][0] + grid[i][0] for j in range(1, n): dp[0][j] = dp[0][j-1] + grid[0][j] # 填充其余位置 for i in range(1, m): for j in range(1, n): dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + grid[i][j] return dp[-1][-1] ``` --- ### 关键点说明 - **初始化处理**:第一行和第一列只能通过单一方向累加得到[^1]。 - **时间复杂度**:$O(mn)$,优于暴力枚举所有路径的指数复杂度。 - **空间优化**:可用滚动数组将空间复杂度优化至$O(n)$。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值