#dDDLDPybttg050505. 1601:【例 5】Banknotes

1601:【例 5】Banknotes

好的,我将这道题整理为清晰的题面格式,并补充样例解释、数据范围与时空限制:


题目描述

原题来自:POI 2005

Byteotian Bit Bank (BBB) 拥有一套先进的货币系统,这个系统一共有 nn 种面值的硬币,面值分别为 b1,b2,,bnb_1, b_2, \dots, b_n。但是每种硬币有数量限制,现在我们想要凑出面值 kk,求最少要用多少个硬币。


输入格式

  • 第一行一个整数 nn
  • 第二行 nn 个整数 b1,b2,,bnb_1, b_2, \dots, b_n,表示硬币的面值;
  • 第三行 nn 个整数 c1,c2,,cnc_1, c_2, \dots, c_n,表示每种硬币的个数;
  • 第四行一个整数 kk,表示要凑出的面值。

输出格式

输出一行一个整数,表示最少需要付的硬币数。


样例

样例输入

3
2 3 5
2 2 1
10

样例输出

3

样例解释

硬币面值:[2,3,5][2,3,5],数量:[2,2,1][2,2,1],要凑出面值 1010

最少硬币数方案:

  • 使用 55 面值硬币 11 枚(剩余 55 需凑)
  • 使用 33 面值硬币 11 枚(剩余 22 需凑)
  • 使用 22 面值硬币 11 枚(剩余 00

总共 33 枚硬币。

另一种方案:5+55+555 硬币只有 11 枚,不行;2+2+2+2+22+2+2+2+2 需要 5522,但只有 22 枚;2+2+3+32+2+3+3 需要 44 枚;所以最少是 33 枚。


数据范围

对于全部数据:

  • 1n2001 \le n \le 200
  • 1b1<b2<<bn2×1041 \le b_1 < b_2 < \dots < b_n \le 2\times 10^4
  • 1ci,k2×1041 \le c_i, k \le 2\times 10^4

时空限制

  • 时间:1000 ms1000 \text{ ms}
  • 内存:524288 KB524288 \text{ KB}

提示
此题为 多重背包 求最小硬币数(每种硬币数量有限),可以用 单调队列优化二进制拆分 转化为 0/1 背包,再求最小值。

方法一:二进制拆分

  • 将每种硬币数量 cic_i 拆成 1,2,4,,2t,r1,2,4,\dots,2^t, r(其中 rr 是剩余部分);
  • 这样每种硬币被拆成 O(logci)O(\log c_i) 个物品,每个物品价值为 bib_i,费用为 11(硬币数);
  • 问题转化为:有 O(nlogk)O(n \log k) 个物品,每个物品体积为 bib_i,价值为 11,求恰好装满 kk 的最小价值(硬币数);
  • 用 DP:dp[x]dp[x] 表示凑出面值 xx 的最少硬币数,初始 dp[0]=0dp[0]=0,其余为 \infty
  • 对每个物品,dp[j]=min(dp[j],dp[jbi]+1)dp[j] = \min(dp[j], dp[j-b_i] + 1)(注意是 0/1 背包,需要倒序枚举 jj)。

复杂度:O(knlogk)O(k \cdot n \log k),在 k2×104k \le 2\times 10^4n200n\le 200 时可行。

方法二:单调队列优化多重背包

  • 对于每种硬币 bib_i,将 dpdp 数组按模 bib_i 的余数分成 bib_i 组;
  • 对于每一组,状态转移为 $dp[j] = \min_{0 \le l \le c_i} \{ dp[j - l\cdot b_i] + l \}$;
  • 可以用单调队列维护窗口 [jcibi,j][j - c_i\cdot b_i, j]dp[jlbi]ldp[j - l\cdot b_i] - l 的最小值,从而 O(1)O(1) 转移。

复杂度:O(nk)O(n \cdot k),更优。

最终答案dp[k]dp[k](若为无穷大则无解,但题目保证有解?实际上可能无解,但根据数据范围应保证有解)。

注意:本题求最小硬币数,初始 dp[0]=0dp[0]=0,其余 dp[i]=dp[i]=\infty,转移取 min\min