题解:AtCoder AT_awc0125_a Warehouse Package Inspection

【题目来源】

AtCoder:A - Warehouse Package Inspection

【题目描述】

高橋负责检查一个大仓库中的货物。仓库里 \(N\) 个货架排成一条直线,按顺序编号为 \(1\)\(N\)。从货架 \(i\) 移动到货架 \(j\) 需要 \(|i - j| \times D\) 分钟,其中 \(D\) 是一个正整数,表示相邻货架之间的移动时间(单位:分钟)。

每个货架上都有需要检查的货物,检查货架 \(i\) 上的货物需要 \(T_i\) 分钟。检查必须在货架前进行,不能在移动过程中进行。此外,高橋必须完成当前货架的检查后才能开始移动去下一个货架;检查和移动不能同时进行。虽然他可能会在移动过程中经过其他货架,但仅仅经过不算作检查。要检查它们,他必须再次移动到该货架并停下。

高橋最初在货架 \(S\) 前面。他可以自由选择先检查哪个货架。高橋从货架 \(S\) 前面移动到第一个要检查的货架,并在那里进行检查。如果他选择先检查货架 \(S\),他可以立即开始检查,移动时间为 \(0\) 分钟。

高橋必须恰好检查所有 \(N\) 个货架一次。他检查货架的顺序可以自由选择。一旦最后一个货架的检查完成,工作即结束,他不需要返回起始位置。

求完成所有货架货物检查所需的最短总时间(所有移动时间与所有检查时间之和)。

【输入】

\(N\) \(D\) \(S\)
\(T_1\) \(T_2\) \(\ldots\) \(T_N\)

  • The first line contains three space-separated integers: \(N\), the number of shelves; \(D\), the travel time between adjacent shelves; and \(S\), the starting shelf number.
  • The second line contains \(N\) space-separated integers \(T_1, T_2, \ldots, T_N\), representing the time required to inspect the goods on each shelf.

【输出】

Print the minimum total time (travel time + inspection time) to inspect the goods on all shelves exactly once in a single line.

【输入样例】

4 2 2
3 1 4 2

【输出样例】

18

【核心思想】

  1. 问题分析:给定 \(N\) 个排成直线的货架,起始位置为货架 \(S\),检查货架 \(i\)\(T_i\) 分钟,相邻货架移动耗时 \(D\)。要求恰好检查所有 \(N\) 个货架一次,求移动时间 + 检查时间的最小值。检查时间总和固定,因此问题转化为最小化移动时间

  2. 算法选择

    • 贪心策略:从起始点 \(S\) 出发,先走向较近的端点(\(1\)\(N\)),再一路走向另一端点
    • 关键观察:要覆盖 \([1, N]\) 所有点,最优路径是"从 \(S\) 到一端,再到另一端"的连续遍历,避免来回折返
  3. 关键步骤

    • 固定成本累加ans = ΣT_i,检查时间与顺序无关,直接累加
    • 计算最优移动路径
      • 到较近端点的距离:tmp = min(S - 1, N - S)
      • \(S\) 先到较近端点,耗时 tmp × D
      • 再从该端点走到另一端点,需经过 \(N - 1\) 个间隔,耗时 (N - 1) × D
    • 总移动时间tmp × D + (N - 1) × D,即 ans += tmp * d + (n - 1) * d
  4. 时间/空间复杂度

    • 时间复杂度:\(O(N)\),读入 \(N\) 个检查时间并累加
    • 空间复杂度:\(O(N)\),存储检查时间数组(可优化至 \(O(1)\)
  5. 贪心策略的核心思想

    • 端点覆盖必然性:要检查所有货架,路径必须覆盖区间 \([1, N]\),因此至少需要从一端走到另一端,基础移动距离为 \(N - 1\)
    • 起始点偏移优化:从 \(S\) 出发,先向较近端点移动可减少"回头路"——若先走远端点,会多走 \(|S - \text{远端}| - |S - \text{近端}|\) 的重复距离
    • 无折返最优:直线上一维覆盖问题,不折返的路径总长度最小,等价于"从 \(S\) 出发的区间覆盖"
    • 检查时间独立性\(ΣT_i\) 为常数,不影响路径选择,只需优化移动距离
    • 适用于一维坐标上的遍历覆盖问题,核心在于消除冗余往返

【算法标签】

贪心

【代码详解】

#include <bits/stdc++.h>
using namespace std;
#define int long long    // 将int定义为long long,避免总时间计算溢出
const int N = 1000005;   // 定义数组最大容量为1000005
int n, d, s, ans;        // n为货架数量,d为相邻货架移动时间,s为起始货架编号,ans记录最短总时间
int a[N];                // a[i]表示检查货架i所需的时间

signed main()            // 使用signed main配合#define int long long
{
    cin >> n >> d >> s;  // 读入货架数n、相邻移动时间d、起始货架s
    for (int i = 1; i <= n; i++)  // 读入每个货架的检查时间
    {
        cin >> a[i];
        ans += a[i];      // 累加所有货架的检查时间(检查时间是固定的,与顺序无关)
    }
    // 计算最优策略下的移动时间:
    // 策略:从s出发,先走到较近的端点(1或n),然后一路走到另一端点
    // 这样只需走一次"回头路"(从s到较近端点),其余都是单向移动

    // tmp:从起始货架s到较近端点的距离(到1的距离为s-1,到n的距离为n-s)
    int tmp = min(s - 1, n - s);  // 取到左端点(s-1)和右端点(n-s)的较小值
    ans += tmp * d;               // 加上从s到较近端点的移动时间

    // 从一端走到另一端需要经过n-1个相邻间隔
    ans += (n - 1) * d;           // 加上从一端走到另一端的移动时间

    cout << ans << endl;          // 输出最短总时间(检查时间+移动时间)
    return 0;
}

【运行结果】

4 2 2
3 1 4 2
18
posted @ 2026-08-03 08:45  团爸讲算法  阅读(7)  评论(0)    收藏  举报