好吧,我已经咖啡因太多,让我们尝试制定一个算法。(感谢所有指出这是一种算法,而不是对数的人。)
第一步似乎是最大可能数量你最大的子单元的总和小于目标。
其次,取下一个最大的子单元,加上与最大子单元的任何可能数量相结合时不等于目标的最大可能数量。
然后,对每个连续较小的亚单位重复上述步骤,但将每个亚单位与较大亚单位数量的每个可能排列进行比较。
在你的脑海里听起来很简单,但在编码的背后却很痛苦。因此,让我们编写一个Perl脚本来完成这项工作。原谅我的丑陋,但我现在真的太激动了,不能这么做。(默认为美国测试案例,您可以在以下两个“my@subunits”行上切换注释英国测试案例或者玩$target和$subsubunits,只要顶部的假设成立。)是的,这很管用。如果perl不在/usr/bin/perl中,您可能需要更改第一行。
(感谢e-troen指出我在第一个版本中漏掉了几个英国硬币。除非你改变目标,否则它们不会影响输出。)
#!/usr/bin/perl-w##假设:#$target是要细分的金额,整数#@subunits是所有可能的子单元的列表#整数,按从大到小的顺序#$target甚至可以被@subunit中的每一项整除我的$目标=100;my@子单位=(25,10,5,1);#标准美国硬币#my@子单位=(50,20,10,5,2,1);#标准英国硬币我的%units_so_for;my@permutations=(0);foreach$unit(@子单元){我的$highestquantity=$target/$unit;foreach$perm(@permutations){QLOOP:用于$quantity(1..$highestquantity){if($unit*$quantity+$perm==$target){$highestquantity=$quantity-1;最后一次QLOOP;}}}my@newperms=@permutations;if(最高数量$){foreach$perm(@permutations){(1..$最高数量){push@newperms,$_*$单元+$perm;}}}@排列=@newperms;$units_so_far{$unit}=$最高数量;}my$outbuff=“”;我的$total=0;foreach(键(%units_so_far)){$total+=$_*$units_so-far{$_};if($unitsso_far{$_}){$outbuff.=美元“面额$_的$units_so_far{$_}”;}}打印“您最多可以有$total,而无需更改$target。\n”;打印“(如果你介意的话,那就是”.$outbuff.“。)\n”;
2001年10月31日:补遗:是的,如果你在子单元列表中添加3或200个(或$target无法平均划分的任何其他数量),这个程序将很高兴地使用你的所有CPU能力和内存,直到你杀死它或系统崩溃,试图以一种非常低效的方式计算无穷大。