0%

P16229 [蓝桥杯 2026 省 A] 外卖配送

题目大意

P16229 [蓝桥杯 2026 省 A] 外卖配送

题目描述

午高峰的外卖站点里,骑手小蓝正紧盯着屏幕上待处理的 NN 个订单。这些订单必须严格按照系统列表中的固定顺序依次配送,不可打乱或跳过。为了顺利完成任务,小蓝计划将这 NN 个订单分成若干个批次进行配送。

站点内停放着 MM 种不同的交通工具,每种工具都具备两个属性:平均路途耗时 AiA_i 和箱体拥挤系数 BiB_i。对于每一个批次,小蓝可以根据该批次订单的数量,从 MM 种工具中独立选择一种最合适的。

假设某一个批次包含 LL 个订单,且小蓝选用第 ii 种交通工具,则该批次的总耗时由以下三部分组成:

  1. 路途耗时:L×AiL \times A_i 秒。

  2. 取餐耗时:由于箱内挤压,整理 LL 个订单需处理 L(L1)2\frac{L(L-1)}{2} 对挤压关系,每对耗时 BiB_i,共计 L(L1)2×Bi\frac{L(L-1)}{2} \times B_i 秒。

  3. 折返耗时:分批配送存在额外的折返成本。处理第一个批次时,由于小蓝默认已在站点装车完毕可以直接出发,此项耗时为 00 秒;但从第二个批次开始,每开启一个新的批次,都必须花费固定的 XX 秒用于返回站点装载下一批订单。

现在,请你帮助小蓝规划最优的分批方案,并计算出送完 NN 个订单所需的最小总耗时。

输入格式

一行包含三个整数 NNMMXX,分别表示订单总数、交通工具的种类数,以及固定耗时。

接下来的 MM 行,每行包含两个整数 AiA_iBiB_i,依次表示第 ii 种交通工具的平均路途耗时与箱体拥挤系数。

输出格式

输出一个整数,表示完成全部 NN 个订单配送任务所需的最小总耗时(单位:秒)。

输入输出样例 #1

输入 #1

1
2
3
5 2 40
10 8
2 20

输出 #1

1
118

说明/提示

【样例说明】

一种最优的方案是分成 22 批配送:

阶段 详情 耗时
11 批(22 单,选工具 22 路途 2×2=42 \times 2 = 4;取餐 2×12×20=20\frac{2 \times 1}{2} \times 20 = 20 2424
折返 固定耗时 4040
22 批(33 单,选工具 11 路途 3×10=303 \times 10 = 30;取餐 3×22×8=24\frac{3 \times 2}{2} \times 8 = 24 5454
合计 < 118\mathbf{118}

【评测用例规模与约定】

对于 30%30\% 的评测用例,1N,M1001 \le N, M \le 100

对于所有评测用例,1N,M50001 \le N, M \le 50001X,Ai,Bi1091 \le X, A_i, B_i \le 10^9

思路讲解

PDF

其实我觉得 AI 说的不好,不过为了方便索引还是贴过来了

其实就是一个完全背包问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Solve() {
cin >> N >> M >> X;
abls.resize(M);
for (int i = 0; i < M; ++i) {
cin >> abls[i][0] >> abls[i][1];
}
dp.resize(N + 2, INF);
for (int L = 1; L <= N; ++L) {
for (int i = 0; i < M; ++i) {
auto [a,b] = abls[i];
dp[L] = min(dp[L], a * L + ((L * (L - 1)) / 2) * b);
}
}
dpN.resize(N + 2, INF);
dpN[0] = 0;
for (int L = 1; L <= N; ++L) {
for (int w = L; w <= N; ++w) {
if (w - L < 0) {
continue;
}
if (dp[L] + dpN[w - L] + X < dpN[w]) {
dpN[w] = dp[L] + dpN[w - L] + X;
}
}
}
cout << dpN[N] - X << "\n";
}

AC代码

AC
https://www.luogu.com.cn/record/273605286

心路历程(WA,TLE,MLE……)