确定硬币组合的算法
最近,我遇到了一个关于编程算法的提示,但我不知道该怎么做。我以前从未真正编写过算法,所以我在这方面还是个新手。
该问题要求编写一个程序来确定收银员根据硬币价值和硬币数量找零的所有可能的硬币组合。例如,一种货币可能有 4 个硬币:2 分、6 分、10 分和 15 分硬币。等于 50 美分的组合有多少种?
我使用的语言是 C++,尽管这并不重要。
编辑:这是一个更具体的编程问题,但是我如何分析 C++ 中的字符串来获取硬币值?它们在文本文档中给出
4 2 6 10 15 50
(其中本例中的数字对应于我给出的示例)
I was recently faced with a prompt for a programming algorithm that I had no idea what to do for. I've never really written an algorithm before, so I'm kind of a newb at this.
The problem said to write a program to determine all of the possible coin combinations for a cashier to give back as change based on coin values and number of coins. For example, there could be a currency with 4 coins: a 2 cent, 6 cent, 10 cent and 15 cent coins. How many combinations of this that equal 50 cents are there?
The language I'm using is C++, although that doesn't really matter too much.
edit: This is a more specific programming question, but how would I analyze a string in C++ to get the coin values? They were given in a text document like
4 2 6 10 15 50
(where the numbers in this case correspond to the example I gave)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
这个问题被称为硬币找零问题。请检查此和此 了解详细信息。此外,如果您搜索“硬币找零”或“动态编程硬币找零”,那么您将获得许多其他有用的资源。
This problem is well known as coin change problem. Please check this and this for details. Also if you Google "coin change" or "dynamic programming coin change" then you will get many other useful resources.
下面是 Java 中的递归解决方案:
Here's a recursive solution in Java:
这看起来有点像分区,只不过您没有使用 1:50 中的所有整数。它看起来也类似于装箱问题,但略有不同:
其实想了想,就是ILP,因此是 NP 困难的。
我建议一些动态编程方法。基本上,您可以定义一个值“余数”并将其设置为您的目标(例如 50)。然后,在每一步中,您都需要执行以下操作:
因此,如果余数为 50,最大的硬币价值 25 和 10,则您将分为两种情况:
下一步(对于每个分支)可能如下所示:
每个分支将分为两个分支,除非:
This seems somewhat like a Partition, except that you don't use all integers in 1:50. It also seems similar to bin packing problem with slight differences:
Actually, after thinking about it, it's an ILP, and thus NP-hard.
I'd suggest some dynamic programming appyroach. Basically, you'd define a value "remainder" and set it to whatever your goal was (say, 50). Then, at every step, you'd do the following:
So if remainder was 50 and the largest coins were worth 25 and 10, you'd branch into two scenarios:
The next step (for each branch) might look like:
Each branch would split into two branches unless:
如果您有 15、10、6 和 2 分硬币,并且您需要找出有多少种不同的方法可以达到 50,您可以
所以你基本上可以将问题分成更小的问题(可能更小的数量和更少的硬币)。当您只有一种硬币类型时,答案当然是微不足道的(要么您无法准确达到规定的金额,要么您可以通过唯一可能的方式达到)。
此外,您还可以通过使用记忆来避免重复相同的计算,例如仅使用 [6, 2] 达到 20 的方法数量并不取决于是否使用 15+15 或 10+10+ 达到已支付的 30 10,所以较小问题 (20, [6, 2]) 的结果可以
被储存和重复使用。
在Python中这个想法的实现如下
If you have 15, 10, 6 and 2 cents coins and you need to find how many distinct ways are there to arrive to 50 you can
So you basically can split the problem in smaller problems (possibly smaller amount and fewer coins). When you have just one coin type the answer is of course trivial (either you cannot reach the prescribed amount exactly or you can in the only possible way).
Moreover you can also avoid repeating the same computation by using memoization, for example the number of ways of reach 20 using only [6, 2] doesn't depend if the already paid 30 have been reached using 15+15 or 10+10+10, so the result of the smaller problem (20, [6, 2]) can
be stored and reused.
In Python the implementation of this idea is the following
至于问题的第二部分,假设您在文件
coins.txt
中有该字符串:现在向量
coins
将包含可能的硬币值。As for the second part of your question, suppose you have that string in the file
coins.txt
:Now the vector
coins
will contain the possible coin values.对于如此少量的硬币,您可以编写一个简单的暴力解决方案。
像这样的东西:
一个非常肮脏的暴力解决方案,打印所有可能的组合。
这是一个非常著名的问题,因此请尝试阅读其他人提供的更好的解决方案。
For such a small number of coins you can write a simple brute force solution.
Something like this:
A very dirty brute force solution that prints all possible combinations.
This is a very famous problem, so try reading about better solutions others have provided.
一种相当愚蠢的方法如下。您构建一个映射“价值 X 的硬币被使用 Y 次”,然后枚举所有可能的组合,并仅选择那些总计达到所需总和的组合。显然,对于每个值 X,您必须检查 Y 的范围从 0 到所需的总和。这会相当慢,但会解决你的任务。
One rather dumb approach is the following. You build a mapping "coin with value X is used Y times" and then enumerate all possible combinations and only select those which total the desired sum. Obviously for each value X you have to check Y ranging from 0 up to the desired sum. This will be rather slow, but will solve your task.
它与背包问题非常相似
It's very similar to the knapsack problem
您基本上必须求解以下方程:50 = a*4 + b*6 + c*10 + d*15,其中未知数为 a、b、c、d。例如,您可以计算每个变量的 d = (50 - a*4 - b*6 - c*10)/15 等。然后,你开始给 d 所有可能的值(你应该从具有最小可能值的那个开始,这里是 d):0,1,2,3,4,然后根据当前的情况开始给 c 所有可能的值d 的值等等。
You basically have to solve the following equation: 50 = a*4 + b*6 + c*10 + d*15, where the unknowns are a,b,c,d. You can compute for instance d = (50 - a*4 - b*6 - c*10)/15 and so on for each variable. Then, you start giving d all the possible values (you should start with the one that has the least possible values, here d): 0,1,2,3,4 and than start giving c all the possible values depending on the current value of d and so on.
将列表向后排序:[15 10 6 4 2]
现在 50 克拉的解决方案可以包含或不包含 15 克拉。
因此,解决方案的数量是使用 [10 6 4 2] 的 50 克拉的解决方案数量(不再考虑 15 克拉硬币)加上 使用的 35 克拉 (=50ct - 15ct) 的解决方案数量[15 10 6 4 2]。对两个子问题重复该过程。
Sort the List backwards: [15 10 6 4 2]
Now a solution for 50 ct can contain 15 ct or not.
So the number of solutions is the number of solutions for 50 ct using [10 6 4 2] (no longer considering 15 ct coins) plus the number of solutions for 35 ct (=50ct - 15ct) using [15 10 6 4 2]. Repeat the process for both sub-problems.
算法是解决问题的过程,它不必采用任何特定的语言。
首先计算出输入:
和输出:
首先解决您能想到的最简单的情况:
结果应该是:
您将如何解决上述问题?
这个怎么样:
这个怎么样?
An algorithm is a procedure for solving a problem, it doesn't have to be in any particular language.
First work out the inputs:
and the outputs:
Solve for the simplest case you can think of first:
the result should be:
How would you solve the above?
How about this:
what about this?
基于 Scala 中的 algorithmist.com 资源的递归解决方案:
Recursive solution based on algorithmist.com resource in Scala:
另一个Python版本:
Another Python version: