- 论坛徽章:
- 0
|
本帖最后由 黑色阳光_cu 于 2011-02-11 22:46 编辑
有12球其大小、形状都一样,其中有一个球重量不一样(不知是轻或重)。给你一把天平,用三次把这个重量不一样的球称(找)出来。
推而广之,有N个球的情况呢?怎么样用Perl解题呢?
这里给出我一年多前写的代码:- #!/bin/env perl
- use strict;
- use warnings;
- # use Data::Dumper;
- my @balls = &ball_init(12);
- my $bad_ball = &ball_find(\@balls);
- if (defined $bad_ball)
- {
- &ball_success($bad_ball);
- }
- else
- {
- &ball_fail();
- }
- <STDIN>;
- ########################################################################
- sub ball_init
- {
- my ($num) = @_;
- my @balls;
- my ($heavy, $error) = (10, 1);
- for (my $n = 1; $n <= $num; $n++)
- {
- push(@balls, [$n, $heavy]);
- }
- my $select = int(rand($num));
- my $plus_or_minus = int(rand(2));
- if ($plus_or_minus)
- {
- $balls[$select]->[1] += $error;
- }
- else
- {
- $balls[$select]->[1] -= $error;
- }
- return @balls;
- }
- sub ball_find
- {
- my @balls = @{$_[0]};
- my ($ref_buf, $deep) = ($_[1], $_[2]);
- $ref_buf = [] if (not defined $ref_buf);
- $deep = 0 if (not defined $deep);
- my (@left, @right, @others);
- ++$deep;
- print "\nA 第$deep次:\n";
- my $length = int(scalar(@balls) / 3 + 0.5);
- $length = 1 if ($length == 0);
- @left = @balls[0 .. $length - 1];
- @right = @balls[$length .. $length * 2 - 1];
- @others = @balls[$length * 2 .. $#balls];
- if (scalar(@balls) < 3)
- {
- return undef if ($#{$ref_buf} == -1);
- my $ball = shift(@$ref_buf);
- print "取回:", &ball_show([$ball]), "\n";
- my $ball2 = shift(@right);
- @right = ($ball);
- print "左边:", &ball_show(\@left), "\n";
- print "右边:", &ball_show(\@right), "\n";
- if (&ball_total_heavy(\@left) == &ball_total_heavy(\@right))
- {
- return $ball2;
- }
- else
- {
- return shift(@left);
- }
- }
- print "左边:", &ball_show(\@left), "\n";
- print "右边:", &ball_show(\@right), "\n";
- print "余下:", &ball_show(\@others), "\n";
- my $heavy_left = &ball_total_heavy(\@left);
- my $heavy_right = &ball_total_heavy(\@right);
- if ($heavy_left == $heavy_right)
- {
- push(@$ref_buf, @left);
- push(@$ref_buf, @right);
- &ball_find(\@others, $ref_buf, $deep);
- }
- else
- {
- push(@$ref_buf, @others);
- if ($heavy_left < $heavy_right)
- {
- &ball_find2(\@left, \@right, $ref_buf, $deep);
- }
- else
- {
- &ball_find2(\@right, \@left, $ref_buf, $deep);
- }
- }
- }
- sub ball_find2
- {
- my @balls = @{$_[0]};
- my @balls2 = @{$_[1]};
- my ($ref_buf, $deep) = ($_[2], $_[3]);
- $ref_buf = [] if (not defined $ref_buf);
- $deep = 0 if (not defined $deep);
- my (@left, @right, @others);
- ++$deep;
- print "\nB 第$deep次:\n";
- my $length = int((scalar(@balls) + scalar(@balls2)) / 3 + 0.5);
- if ((scalar(@balls) == 1 and scalar(@balls2) <= 2) or (scalar(@balls2) == 1 and scalar(@balls) <= 2))
- {
- my $swp = 0;
- if (scalar(@balls) != 1)
- {
- $swp = 1;
- my @tmp = @balls;
- @balls = @balls2;
- @balls2 = @tmp;
- }
- if (@balls2 == 2)
- {
- push(@left, shift(@balls2));
- push(@right, shift(@balls2));
- }
- else
- {
- if ($#{$ref_buf} == -1)
- {
- return undef;
- }
- my $ball = shift(@$ref_buf);
- print "取回:", &ball_show([$ball]), "\n";
- push(@left, $ball);
- push(@right, shift(@balls2));
- }
- print "左边:", &ball_show(\@left), "\n";
- print "右边:", &ball_show(\@right), "\n";
- my $heavy_left = &ball_total_heavy(\@left);
- my $heavy_right = &ball_total_heavy(\@right);
- if ($heavy_left == $heavy_right)
- {
- return shift(@balls);
- }
- elsif ($swp xor $heavy_left < $heavy_right)
- {
- return shift(@right);
- }
- else
- {
- return shift(@left);
- }
- }
- else
- {
- my (@a1, @a2, @a3, @b1, @b2, @b3);
- my $n = int(scalar(@balls) / 2);
- @a1 = @balls[0 .. $n - 1];
- @a2 = @balls[$n .. $n * 2- 1];
- @a3 = @balls[$n * 2 .. $#balls] if ($n * 2 <= $#balls);
- my $n2 = $length - $n;
- if ($n2 > 0)
- {
- @b1 = @balls2[0 .. $n2 - 1];
- @b2 = @balls2[$n2 .. $n2 * 2 - 1];
- @b3 = @balls2[$n2 * 2 .. $#balls2] if ($n2 * 2 <= $#balls2);
- }
- else
- {
- @b3 = @balls2;
- }
- @left = (@a1, @b1);
- @right = (@a2, @b2);
- @others = (@a3, @b3);
- print "左边:", &ball_show(\@left), "\n";
- print "右边:", &ball_show(\@right), "\n";
- print "余下:", &ball_show(\@others), "\n";
- my $heavy_left = &ball_total_heavy(\@left);
- my $heavy_right = &ball_total_heavy(\@right);
- if ($heavy_left == $heavy_right)
- {
- push(@$ref_buf, @left);
- push(@$ref_buf, @right);
- if (scalar(@a3) == 0 or scalar(@b3) == 0)
- {
- my $heavy_flag = scalar(@a3) == 0 ? 1 : 0;
- &ball_find3(\@others, $heavy_flag, $ref_buf, $deep);
- }
- else
- {
- &ball_find2(\@a3, \@b3, $ref_buf, $deep);
- }
- }
- elsif ($heavy_left < $heavy_right)
- {
- push(@$ref_buf, @right);
- push(@$ref_buf, @others);
- if (scalar(@a1) == 0 or scalar(@b2) == 0)
- {
- my $heavy_flag = scalar(@a1) == 0 ? 1 : 0;
- &ball_find3([@a1, @b2], $heavy_flag, $ref_buf, $deep);
- }
- else
- {
- &ball_find2(\@a1, \@b2, $ref_buf, $deep);
- }
- }
- else
- {
- push(@$ref_buf, @left);
- push(@$ref_buf, @others);
- if (scalar(@a2) == 0 or scalar(@b1) == 0)
- {
- my $heavy_flag = scalar(@a2) == 0 ? 1 : 0;
- &ball_find3([@a2, @b1], $heavy_flag, $ref_buf, $deep);
- }
- else
- {
- &ball_find2(\@a2, \@b1, $ref_buf, $deep);
- }
- }
- }
- }
- sub ball_find3
- {
- my @balls = @{$_[0]};
- my ($heavy_flag, $ref_buf, $deep) = ($_[1], $_[2], $_[3]);
- $ref_buf = [] if (not defined $ref_buf);
- $deep = 0 if (not defined $deep);
- my (@left, @right, @others);
- return shift(@balls) if (scalar(@balls) == 1);
- ++$deep;
- print "\nC 第$deep次:\n";
- my $length = int(scalar(@balls) / 2);
- @left = @balls[0 .. $length - 1];
- @right = @balls[$length .. $length * 2 - 1];
- print "左边:", &ball_show(\@left), "\n";
- print "右边:", &ball_show(\@right), "\n";
- if ($length * 2 <= $#balls)
- {
- @others = @balls[$length * 2 .. $#balls];
- print "余下:", &ball_show(\@others), "\n";
- }
- my $heavy_left = &ball_total_heavy(\@left);
- my $heavy_right = &ball_total_heavy(\@right);
- if ($heavy_left == $heavy_right)
- {
- return shift(@others) if (scalar(@others) == 1);
- push(@$ref_buf, @left);
- push(@$ref_buf, @right);
- &ball_find3(\@others, $heavy_flag, $ref_buf, $deep);
- }
- else
- {
- my @balls;
- if ($heavy_flag xor $heavy_left < $heavy_right)
- {
- return shift(@left) if (scalar(@left) == 1);
- @balls = @left;
- push(@$ref_buf, @right);
- push(@$ref_buf, @others);
- }
- else
- {
- return shift(@right) if (scalar(@right) == 1);
- @balls = @right;
- push(@$ref_buf, @left);
- push(@$ref_buf, @others);
- }
- &ball_find3(\@balls, $heavy_flag, $ref_buf, $deep);
- }
- }
- sub ball_total_heavy
- {
- my $heavy = 0;
- foreach my $ball (@{$_[0]})
- {
- $heavy += $ball->[1];
- }
- return $heavy;
- }
- sub ball_show
- {
- my $string = "";
- foreach my $ball (@{$_[0]})
- {
- my ($id, $heavy) = @$ball;
- $string .= "[$id,$heavy] ";
- }
- $string =~ s/\s+$//;
- return $string;
- }
- sub ball_success
- {
- my ($id, $heavy) = @{$_[0]};
- print "\n缺陷球为:[$id,$heavy]\n";
- }
- sub ball_fail
- {
- print "\n无解\n";
- }
复制代码 |
|