0%

2025 United Kingdom and Ireland Programming Contest (UKIEPC 2025) 2025 英国 ICPC——D. Depot(仓库)(当以比较整体的视角去看待一个问题,发现无法解决的时候,应该要切换回比较个体的视角,就是要这个粒度要更加细一点,粒度更加细一点,可能有的时候就会有思路了)(可以去掉某些限制,看看是否可以想出来)(完全背包问题)

题目大意

注意这道题目,其表述有点问题,应该要这么理解比较好。就是说在任何情况下,这个仓库容量都不能爆

核心目标

nn 个顺序进行的精炼阶段中,利用初始物料 1 的数量 ss 和共享仓库容量 kk,通过选择不同的转化机器(物料 ii+1i \to i+1),计算最终能获得的物料 nn 的最大数量。

关键约束

  • 处理顺序:必须严格按照 12n1 \to 2 \to \dots \to n 的顺序处理。一旦开始处理下一阶段,就不能再返回处理上一阶段的物料。

  • 机器转化:每个阶段有若干机器可选,每台机器消耗 MIM_I 单位物料 ii 并产出 MOM_O 单位物料 i+1i+1。同一阶段内可以多次、多种类地使用机器。

  • 仓库容量限制:仓库为所有物料共享。在进行第 ii+1i \to i+1 阶段转化时,仓库内剩余的物料 ii 数量与已产出的物料 i+1i+1 数量之和在任何时刻都不能超过 kk

  • 物料处置:为了腾出空间满足容量限制,可以随时丢弃仓库内的物料。

样例解释

  • 样例 3 (s=4,k=10s=4, k=10,机器 1: 消耗 2 产 3)

    1. 第一次运行机器:消耗 2 个物料 1,产出 3 个物料 2。此时仓库内有 2 个物料 1 和 3 个物料 2,总数 2+3=5102+3=5 \le 10
    2. 第二次运行机器:再消耗 2 个物料 1,产出 3 个物料 2。此时仓库内有 0 个物料 1 和 6 个物料 2,总数 0+6=6100+6=6 \le 10
      最终产出:6。
  • 样例 4 (s=4,k=7s=4, k=7,机器 1: 消耗 2 产 4)

    1. 第一次运行机器:消耗 2 个物料 1,产出 4 个物料 2。仓库总量为 2+4=672+4=6 \le 7
    2. 第二次尝试:如果再次运行机器,产出 4 个物料 2,则总量将变为 0+8=80+8=8。由于仓库上限 k=7k=7,实际产出的物料 2 最终只能封顶为 7。
      最终产出:7。
  • 样例 5 (s=7,k=7s=7, k=7,机器 1: 消耗 3 产 5)

    1. 直接转化尝试:若消耗 3 个物料 1,剩 4 个,产出 5 个,总量 4+5=9>74+5=9 > 7,操作非法。
    2. 调整策略:必须先丢弃 2 个物料 1,使初始物料 1 降为 5。
    3. 运行机器:消耗 3 个物料 1,剩 2 个,产出 5 个,总量 2+5=772+5=7 \le 7。此时剩余物料 1 不足以再次运行机器。
      最终产出:5。

样例解释

样例 关键参数 过程说明 结果
样例 3 s=4,k=10s=4, k=10 机器 (1, 2, 3) 1. 消耗 2 个物料 1 \to 产出 3 个物料 2。仓内存放:2 (剩) + 3 (新) = 5 10\le 10
  1. 再消耗 2 个物料 1 \to 产出 3 个物料 2。仓内存放:0 (剩) + 6 (新) = 6 10\le 10。 | 6 |
    | 样例 4 | s=4,k=7s=4, k=7 机器 (1, 2, 4) | 1. 消耗 2 个物料 1 \to 产出 4 个物料 2。仓内存放:2 + 4 = 6 7\le 7
  2. 计划再产出 4 个,但总量将达 0+8=8>70+8=8 > 7,受限于 k=7k=7,实际产出封顶为 7。 | 7 |
    | 样例 5 | s=7,k=7s=7, k=7 机器 (1, 3, 5) | 1. 若直接转化:消耗 3 个剩 4 个,产出 5 个,总量 4+5=9>74+5=9 > 7(非法)。
  3. 必须先丢弃 2 个物料 1,剩 5 个。消耗 3 个剩 2 个,产出 5 个,总量 2+5=772+5=7 \le 7
  4. 剩余 2 个物料 1 不足消耗,停止。 | 5 |

思路讲解

我们可以先想,如果我们把这个ware house的这个容量的这个限制去掉的话,是不是会好做很多?去掉的话,其实就是跑 n 个背包就好了(注意,这个其实是完全背包),只要我们能够最大化每个产品的数量,那么就一定可以贪心的得到最多的 N 的数量。

为什么是外层W内层机器呢?这个的原因其实是这样子,完全背包我们不是说那么在意这个顺序,我们可以呃外层是物品,内层是W。但是是这样子,完全背包之所以不在意乎这个顺序,是因为你放入背包当中的物品无论以什么顺序放入都无所谓。但是这道题目由于其能够所产生的利益是与原来的这个 dp 是相关的,如果说你先用一个机器,这个机器的效率比较高,产生的DP比较多,就产生的这个值比较多的话,然后你后运行一个机器。它也是一个效率比较高的机器的话,那么可能就你就超出了题目的仓库容量的限制。呃,说白了就是这道题目先运行哪个机器,后运行哪个机器是非常重要的。我们不能够忽略这个顺序。(不能够忽略的原因已在上面给出。)

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
ll cur_material=St_material;
for (int i=2;i<=N;++i) {
for (int w=1;w<=cur_material;++w) {
// 顺序遍历,利用完全背包的这个性质。
// 呃,理论上来说
// W它有的时候不是每次都是每个输入物料都是有用的嘛。所以说它相当于也是有这个丢弃的这个作用。
// 外层w内层机器,保证B→A交替序列能被捕获
for (auto [input,output]:material_machine_mtx[i]) {
if (w-input<0) {
continue;
}
if (cur_material-w+dp_knapsack[i][w-input]+output <= K_depot) {
dp_knapsack[i][w]=max(dp_knapsack[i][w],dp_knapsack[i][w-input]+output);
}else {
// 黄色荧光的是常量,
ll output_rem=K_depot-output-cur_material+w;
if (output_rem<0) {
continue;
}
dp_knapsack[i][w]=max(dp_knapsack[i][w],output_rem+output);
}
}
}
cur_material=*max_element(all(dp_knapsack[i]));
}

AC代码

AC
https://qoj.ac/submission/2019893
AC
https://codeforces.com/gym/106157/submission/362107850

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