免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: py
打印 上一主题 下一主题

给大家发一个澳大利亚研究生课程作业题 [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
11 [报告]
发表于 2011-03-25 12:51 |只看该作者
回复  昭襄王

是的,原本描述的是很详细的,包括有多少种钱币,各多少个,票的面值是多少。还包括图形界 ...
py 发表于 2011-03-25 12:13



    我觉得这个条件非常重要,如果没有这个条件将没法正确处理如下流程:
用户消费了40美分,但是蛋疼的给了3个1美元(或1个1美元1个2美元,或几个50美分等等),如果没有分捡入库操作,原金库只有1个1美元,加上其他零钱还是不足所需金额,而事实上加上用户多给的2美元,零钱是足够的。

考虑到自动售货机是需要循环作业的,这个条件就更不可或缺了。

论坛徽章:
2
白羊座
日期:2013-10-29 13:29:222015亚冠之全北现代
日期:2015-10-25 08:13:02
12 [报告]
发表于 2011-03-25 13:16 |只看该作者
本帖最后由 miniqq 于 2011-03-25 14:32 编辑

回复 1# py

Hi, 我给出一个:
首先,我对题目的理解是: 给定一个数A, 从数组 B中找出几个数,使其和等于A,并且大数优先. 通常A比B中最大的数大.

说明,我省略了两个步骤: 把数组变为hash, 从大到小排列不重复的数组 @list.

脚本:

  1. #!/usr/bin/perl -w
  2. #

  3. use strict;

  4. my %hash = ();

  5. $hash{5} = 1;
  6. $hash{20} = 3;
  7. $hash{50} = 1;
  8. $hash{100} = 1;

  9. my $osum = 160;
  10. my $sum = $osum;
  11. my @list = (100,50,20,5);
  12. my %result;
  13. my @give;
  14. my $trys = scalar(@list);

  15. retry:
  16. foreach my $c (@list) {
  17.         if ($sum >= $c and $sum > 0) {
  18.                 if ($hash{$c} == 1) {
  19.                         $sum = $sum - $c;
  20.                         $result{$c} = 1;
  21.                         push @give, $c;
  22.                         next;
  23.                 }
  24.                 elsif ($hash{$c} > 1) {
  25.                         my $i = 0;
  26.                         for($i=0, $i < $hash{$c}, ++$i) {
  27.                                 if ($sum >= $c and $sum > 0) {
  28.                                         $sum = $sum - $c;
  29.                                         $result{$c}++;
  30.                                         if ($result{$c} > $hash{$c}) {
  31.                                                 print "not found\n";
  32.                                                 exit 1;
  33.                                         }
  34.                                         push @give, $c;
  35.                                         next;
  36.                                 }
  37.                         }
  38.                 }
  39.         }
  40.         else {
  41.                 next;
  42.         }
  43. }

  44. if ($sum > 0) {
  45.         $sum = $osum;
  46.         %result = ();
  47.         my $last;
  48.         if(scalar(@give) >=2) {
  49.                 pop @give;
  50.                 $last = pop @give;
  51.         }
  52.         else {
  53.                 $last = pop @give;
  54.         }
  55.         $trys--;
  56.         if ($trys < 1 or !$last) {
  57.                 print "not found\n";
  58.                 exit 1;
  59.         }
  60.         @give = ();
  61.         @list = grep (!/$last/, @list);
  62.         goto retry;
  63. }

  64. if ($sum == 0) {
  65. foreach my $find (keys %result) {
  66.         print "$find\t$result{$find}\n";
  67. }

  68. }
  69. else {
  70.         print "not found\n";
  71. }

复制代码
觉得还不完善.不知哪里要改一下.

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
13 [报告]
发表于 2011-03-25 13:34 |只看该作者
我觉得这个条件非常重要,如果没有这个条件将没法正确处理如下流程:
用户消费了40美分,但是蛋 ...
昭襄王 发表于 2011-03-25 12:51


呵呵,看来你是好好想过这个问题了。当初做这个作业的时候,因为这个问题我还找老师争论过。
我问他“找钱的来源是不是要把用户扔进去的钱也算在内?”
他说“whatever”。他说算在内和不算在内,在代码层面上只会有很小的改动。
后来想想也是,如果算在一起找钱,那在计算找赎的时候就把用户扔的钱加在一起算就是了,代码改动很小。

为这个事我还去看了那个自动售票机,晚上会有警察把那个机器打开,我仔细观察了一下,实际情况是,那里面有不记期数的硬币,不太可能出现“需要把当前用户放进去的那几个硬币也算作找赎才可以的情况”。
而且,在买票的时候,当你放入的钱,达到或超过了当前票面值的时候,这个时候机器会吐出一张票,并吐出找赎。然后你会听到“哗啦”一声,你刚才放入的钱才真正掉入售票机里面。
所以,很有可能真实的售票机只是从机器里面找钱的,并没有算你放进去的硬币。

PS.其实这样也是简化工业设计,钱从两个地方出来,你说你那出钱的口做在哪好啊。。。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
14 [报告]
发表于 2011-03-25 13:45 |只看该作者
回复  py

Hi, 我给出一个:
首先,我对题目的理解是: 给定一个数A, 从数组 B中找出几个数,使其和等于A,并 ...
miniqq 发表于 2011-03-25 13:16


我试了一下,你可能漏掉了一些可能性,比如,按照你现在脚本上写的样子,如果找赎是80的时候,结果应该提示无法找出。但程序会死循环。

另外,如果售票机初始库存是
  1. $hash{5} = 1;
  2. $hash{20} = 2;
  3. $hash{50} = 1;

  4. my $osum = 60;
  5. my $sum = $osum;
  6. my @list = (50,20,5);
复制代码
找赎是60的时候,也有错误,会找出三个20来。

论坛徽章:
0
15 [报告]
发表于 2011-03-25 14:31 |只看该作者
  1. sub get {
  2.     my $need    = shift;
  3.     my $hash    = shift;
  4.     my @array   = @_;
  5.     my @arr = sort { $b <=> $a } grep { $_ <= $need and $hash->{ $_ } } keys %$hash;
  6.     foreach ( @arr ){
  7.         return join ',', @array, $_ if $_ == $need;
  8.         my %hash = %$hash;
  9.         $hash{ $_ }--;
  10.         my $ret = get( $need - $_, \%hash, @array, $_ );
  11.         return $ret if $ret;
  12.     }
  13. }

  14. while(<DATA>){
  15.     chomp;
  16.     print "$_ => ";
  17.     print get $_, {
  18.         1   => 4,
  19.             5        => 1,
  20.             20        => 3,
  21.             50        => 1,
  22.             100        => 1
  23.     };
  24.     print "\n";
  25. }

  26. __DATA__
  27. 160
  28. 150
  29. 111
复制代码
回复 1# py

论坛徽章:
2
白羊座
日期:2013-10-29 13:29:222015亚冠之全北现代
日期:2015-10-25 08:13:02
16 [报告]
发表于 2011-03-25 14:33 |只看该作者
回复 14# py


    改了一下,你再试试.

论坛徽章:
0
17 [报告]
发表于 2011-03-25 14:41 |只看该作者
回复 14# py
  1. #!/usr/bin/perl -w
  2. use warnings;
  3. use strict;
  4. use Data::Dumper;
  5. my %hash = ();
  6. $hash{$ARGV[1]} = $ARGV[2];
  7. $hash{$ARGV[3]} = $ARGV[4];
  8. $hash{$ARGV[5]} = $ARGV[6];
  9. $hash{$ARGV[7]} =$ARGV[8];
  10. my $osum = $ARGV[0];
  11. my $sum = $osum;
  12. my @list = (100,50,20,5);
  13. my %result;
  14. my @give;
  15. retry:
  16. foreach my $c (@list) {
  17.         if ($sum >= $c and $sum > 0) {
  18.                 if ($hash{$c} == 1) {
  19.                         $sum = $sum - $c;
  20.                         $result{$c} = 1;
  21.                         push @give, $c;
  22.                         next;
  23.                 }
  24.                 if ($hash{$c} > 1) {
  25.                         for(my $i=0; $i < $hash{$c}; $i++) {
  26.                                 if ($sum >= $c and $sum > 0) {
  27.                                         $sum = $sum - $c;
  28.                                         $result{$c}++;
  29.                                         push @give, $c;
  30.                                         next;
  31.                                 }
  32.                         }
  33.                 }
  34.         }
  35.         else {
  36.                 next;
  37.         }
  38. }
  39. if ($sum != 0) {
  40.         $sum = $osum;
  41.         %result = ();
  42.                 if ($#give == 0) {
  43.                         print "error\n";
  44.                         exit;
  45.                 }
  46.         pop @give;
  47.         my $last = pop @give;
  48.         @give = ();
  49.         @list = grep (!/$last/, @list);
  50.         goto retry;
  51. }
  52. foreach my $find (sort {$b<=>$a} keys %result) {
  53.         print "$find\t$result{$find}\n";
  54. }
复制代码

论坛徽章:
2
白羊座
日期:2013-10-29 13:29:222015亚冠之全北现代
日期:2015-10-25 08:13:02
18 [报告]
发表于 2011-03-25 14:46 |只看该作者
回复 15# guap514


    好,递归好!

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
19 [报告]
发表于 2011-03-25 14:47 |只看该作者
回复 13# py


    whaterer...就是说不考虑缺少任何一种面额的硬币了?那何必规定目前每种有几枚呢?假设和目的是矛盾的。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
20 [报告]
发表于 2011-03-25 14:48 |只看该作者
perl有goto真是方便啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP