下面的函数 Count 计算总计达到给定数量的最小硬币数量。
∇ R ← d AppendQuotRem qrs; oldR; q; r
oldR ← 2 ⊃ (⍴qrs) ⊃ qrs
q ← ⌊oldR ÷ d
r ← oldR - d × q
R ← qrs , ,⊂(q r)
∇
∇ R ← Count amount; ds; qrs; qs
ds ← 1 5 10 25 50 ⍝ coin denominations in cents
qrs ← ⊃AppendQuotRem/ ds , ⊂,⊂(0 amount)
qs ← 1 ⊃¨ qrs
R ← ds ,[0.5] ⌽1 ↓ qs
∇
我为每种面额计算商和余数。余数用于涉及下一个面额的计算。有没有更短和/或更直接的方法来解决问题?
答案 0 :(得分:1)
change-making problem实际上是quite hard。完整的APL方法是included in the dfns workspace。
您的算法很贪婪,对于某些组的硬币面额,这给出了错误的结果。它恰好可以解决您在示例中使用的集合。让我们修改您的Count
函数:
∇ R ← Count134 amount; ds; qrs; qs
ds ← 1 3 4 ⍝ coin denominations in cents
qrs ← ⊃AppendQuotRem/ ds , ⊂,⊂(0 amount)
qs ← 1 ⊃¨ qrs
R ← ds ,[0.5] ⌽1 ↓ qs
∇
Count134 6
1 3 4
2 0 1
这使用三个硬币,但是两个3美分的硬币是正确的答案:
1 3 4
0 2 0
话虽如此,一般的造币系统被设计成贪婪算法将产生最佳结果。因此,这是您的代码的简化:
∇ R ← d AppendQuotRem qrs; oldR; q; r
oldR ← 1 ↑ qrs
q ← ⌊oldR ÷ d
r ← d | oldR
R ← r , q , 1 ↓ qrs
∇
∇ R ← Count amount; ds
ds ← 1 5 10 25 50 ⍝ coin denominations in cents
R ← ds ,[0.5] ⊃AppendQuotRem/ 1 ↓ ds , amount
∇
答案 1 :(得分:0)
贪婪算法,其中货币价值为100 50 20 10 5 1个单位。
∇r←Greedy w;i;d;k;x;l
r←⍬⋄i←1⋄d←100 50 20 10 5 1⋄l←≢d
r←r,k←⌊w÷x←d[i]⋄w-←k×x⋄→2×⍳l≥i+←1
r←2 l⍴d,r
∇
Prova←{+/⍵[1;]×⍵[2;]}
m←Greedy 125
m
100 50 20 10 5 1
1 0 1 0 1 0
Prova m
125