Backtracking algorithm, non-algorithmic master do not enter!

Source: Internet
Author: User
Tags php write
This post was last edited by xuzuning on 2011-06-10 14:40:16

Given the items n pieces, their weight is w[0],w[1],......w[n-1], the value of the goods is v[0],v[1],......v[n-1], and another backpack, it can hold the total weight of W. Design an item selection scheme that requires that the total weight of the items selected from these n items not exceed the capacity of the backpack w, so that the value of the selected item is the largest.

This is a very common backpack backtracking algorithm, who can write in PHP!


Note: The algorithm-independent reply will be ruthlessly deleted! Moderator


Reply to discussion (solution)

This question will take at least one hours, I say train of thought, let others do it.

1. Sort the array of W to select items less than W weight (assignment array p),
2. The Cartesian product array is computed for the P array, and the sum of the items in all subsets is selected and less than the W weight (Assignment array R).
3. Convert the entries in each subset of the r array to the corresponding V-values and sum them separately (array WV),
4. Sort the WV array and derive the key to the large value as the result.

2 ... Select a subset of the items in all subsets and less than the W weight
-----------------------------
is to sum the subset items, such as
{1,3,5}--(1+3+5) < W
{2,6}--(2+6) < W

In addition, this is a bit different from the backtracking algorithm, and the subset computed by the backtracking algorithm is sequential,
The subset of requirements calculated here is not sequential, more like the calculation of the Cartesian product multipoint.

Coolesting a good idea.

In fact, the idea of this problem has long been on the network,

Useful C Write, also useful C + + write, even C # has, is not written in PHP

So want to see our csdn PHP section whether there are enthusiastic people willing to use PHP to write a

Don't go to Baidu when you can not find PHP write back case

Coolesting a good idea.

In fact, the idea of this problem has long been on the network,

Useful C Write, also useful C + + write, even C # has, is not written in PHP

So want to see our csdn PHP section whether there are enthusiastic people willing to use PHP to write a

Don't go to Baidu when you can not find PHP write back case

Well, this great mission is yours.

To verify the correctness of the algorithm, it is suggested to give the original data and answer

The algorithm is not difficult, it can be transplanted from other languages. Of course, innovation is better.

1. Sort the array of W to select items less than W weight (assignment array p),
2. The Cartesian product array is computed for the P array, and the sum of the items in all subsets is selected and less than the W weight (Assignment array R).
The first step produces only one-dimensional arrays, so how does the Cartesian product of the second step calculate?
If it's a combination, it's simple.

Nagging boss didn't see it, the first floor with a poor lifting method, all the combination of first statistics, and then one item to compare to

Reference 1 Floor coolesting's reply:
1. Sort the array of W to select items less than W weight (assignment array p),
2. The Cartesian product array is computed for the P array, and the sum of the items in all subsets is selected and less than the W weight (Assignment array R).

The first step produces only one-dimensional arrays, so how does the Cartesian product of the second step calculate?
If it's a combination, it's simple. He's wrong, it should be the closure of the one-dimensional array that was produced in the first step.

Can this be considered, in all combinations less than the weight of the required items, the value of the item divided by the weight of the item, a ratio is obtained from the large to the small, from the front to find a combination of the maximum ratio of less than or equal to the required weight.

$ar =array (' 1 ' = ' 3 ', ' 4 ' = ' + ', ' 5 ' = ' 3 ', ' 6 ' = ' 7 ', ' 2 ' + ' 9 ', ' + ' = ' 8 ', ' 9 ' = ' 15 ' , ' 6 ');
$a =array ();
$w =10;//Required Weight
foreach ($ar as $key = = $value) {
if ($key <= $w) {$a [$key]= $value;}
}
Print_r ($a);
foreach ($a as $key = = $value) {
$a [$key]= $value/$key;
}
Arsort ($a);
Print_r ($a);
$sum = 0;
$b =array ();
foreach ($a as $key = = $value) {
$sum = $sum + $key;
if ($sum > $w) {break;};
$b [$key]= $ar [$key];
}

Print_r ($b);

Can this be considered, in all combinations less than the weight of the required items, the value of the item divided by the weight of the item, a ratio is obtained from the large to the small, from the front to find a combination of the maximum ratio of less than or equal to the required weight.

$ar =array (' 1 ' = ' 3 ', ' 4 ' = ' + ', ' 5 ' = ' 3 ', ' 6 ' = ' 7 ', ' 2 ' + ' 9 ', ' + ' = ' 8 ', ' 9 ' = ' 15 ' , ' 6 ');
$a =array ();
$ ... No, for example, I have 9=>8,4=>3,10=>10, three items, a backpack of 11, your algorithm comes out is 10=>10, and obviously should be 9=>8,4=>3 is right

Can this be considered, in all combinations less than the weight of the required items, the value of the item divided by the weight of the item, a ratio is obtained from the large to the small, from the front to find a combination of the maximum ratio of less than or equal to the required weight.

$ar =array (' 1 ' = ' 3 ', ' 4 ' = ' + ', ' 5 ' = ' 3 ', ' 6 ' = ' 7 ', ' 2 ' + ' 9 ', ' + ' = ' 8 ', ' 9 ' = ' 15 ' , ' 6 ');
$a =array ();
$ ...

Like this can not appear two items of the same price, so say not to the overall

Can this be considered, in all combinations less than the weight of the required items, the value of the item divided by the weight of the item, a ratio is obtained from the large to the small, from the front to find a combination of the maximum ratio of less than or equal to the required weight.

$ar =array (' 1 ' = ' 3 ', ' 4 ' = ' + ', ' 5 ' = ' 3 ', ' 6 ' = ' 7 ', ' 2 ' + ' 9 ', ' + ' = ' 8 ', ' 9 ' = ' 15 ' , ' 6 ');
$a =array ();
$w ...

I use a key to represent the weight, and the value represents the price.

 = $ms) {$_r = $arr [$i];} $ms = $as;} Return $_r;} $_RR = Check_m ($_t, $m, 1); $_r=check_max ($_RR); echo "
";p Rint_r ($_r), echo"
";? >

Reference 10 Floor Blizzf99 's reply:

Can this be considered, in all combinations less than the weight of the required items, the value of the item divided by the weight of the item, a ratio is obtained from the large to the small, from the front to find a combination of the maximum ratio of less than or equal to the required weight.

$ar =array (' 1 ' = ' 3 ', ' 4 ' = ' + ', ' 5 ' = ' 3 ', ' 6 ' = ' 7 ', ' 2 ' + ' 9 ', ' + ' = ' 8 ', ' 9 ' = ' 15 ' , ' 15 ...

It does not take into account the same weight situation, if the weight is the same, should take the high price of the.

This post was last edited by xuzuning on 2011-06-10 14:01:34

Class Backtracking {private $c = 0;   Backpack capacity Private $n = 0;   Number of items Private $w = Array ();   Item weight Array Private $p = Array ();   Item value Array Private $CW = 0;   Current weight Private $CP = 0;   Current value Private $BESTP = 0;   Current optimal value private $d;  Unit weight value Private $st = Array ();    function __construct ($w, $p, $c) {$this->w = $w;    $this->p = $p;    $this->c = $c;    $this->n = count ($w);    $this->d = Array_map (Array ($this, ' calculation '), $this->p, $this->w);  Array_multisort ($this->d, Sort_desc, $this->w, $this->p);    } Private Function calculation ($p, $w) {if ($w = = 0) return $p;  return $p/$w;  } function Bestvalue () {return $this->bestp; The function parse ($i =0) {if ($this->debug) echo ", $i ($this-&GT;CW, $this->cp) [". Join (', ', $this->st). "]
\ n "; if ($i > $this->n-1) {//Reach leaf node $this->bestp = $this->cp; if ($this->debug) echo "<= $i ($this-&GT;CW, $this->cp) [". Join (', ', $this->st). "]
\ n "; Return } $this->st[] = $i; if ($this-&GT;CW + $this->w[$i] <= $this->c) {$this-&GT;CW + = $this->w[$i]; $this-&GT;CP + = $this->p[$i]; $this->parse ($i + 1); Depth priority $this-&GT;CW-= $this->w[$i]; $this-&GT;CP-= $this->p[$i]; if ($this->bound ($i + 1) > $this-&GT;BESTP) {//forward probing if ($this->debug) echo "= = $i ($this-&GT;CW, $t HIS-&GT;CP) [". Join (', ', $this->st)."]
\ n "; Array_pop ($this->st); $this->parse ($i + 1); if ($this->debug) echo "<-$i ($this-&GT;CW, $this->cp) [". Join (', ', $this->st). "]
\ n "; The Private Function Bound ($i) {//the upper bound of the corresponding value of the COMPUTE node $cleft = $this->c-$this->cw; Remaining capacity $b = $this->cp; Load items in descending order of item unit weight value while ($i < $this->n && $this->w[$i] <= $cleft) {$cleft-= $this->w [$i]; $b + = $this->p[$i]; $i + +; if ($i <= $this->n) {$b + = $this->d[$i] * $cleft; } return $b; } function display () {foreach ($this->st as $k) $r [] = Array (' W ' = $this->w[$k], ' V ' = $this p[$k]); return $r; }}


For #11 data
$ar = Array (9=>8, 4=>3, 10=>10);
$p = new Backtracking (Array_values ($ar), Array_keys ($ar), 11);
$p->parse ();
echo $p->bestvalue (); 13
Print_r ($p->display ());

Array
(
[0] = = Array
(
[W] = 3
[V] = 4
)

[1] = = Array
(
[W] = 8
[V] = 9
)

)


$ar =array (Array (1,3), array (3,2), Array (4,8), Array (9,1), Array (11,7), Array (3,12), Array (9,8), Array (7,3));//value 1 means weight, A value of 2 indicates a price
$w = 10;
$a =array ();
$b =array ();
$c =array ();
for ($i =0; $i
if ($ar [$i][0]<= $w) {
$a [$i]= $ar [$i][0];//weight Array
$b [$i]= $ar [$i][1]/$ar [$i][0]; An array of price-to-weight ratios
}
}
Print_r ($a);
Print_r ($b);
Arsort ($b);
$sum = 0;
foreach ($b as $key = = $value) {
$sum = $sum + $a [$key];
if ($sum > $w) {break;};
$c []= $ar [$key];
}
Print_r ($c);

Start working $w = 9; $arrWeight = Array (8, 2, 5, 7); $arrValue  = Array (7, 3, one, and); $arr = Array_combine ($arrWeight, $ Arrvalue); Arsort ($arr); $_w = 0; $arrSelect = array ();//Start filtering foreach ($arr as $key = $val) {$_w + = $key; if ($_w <= $w) {$a rrselect[$key] = $val;} else {$_w-= $key;  The retrospective}}print_r ($arrSelect) is used here;


Trouble Master to see if it is reasonable

$SW =;   Backpack weight is 23$a = Array (2, 3, 44, 5, 15, 12); Value $w = Array (5, 5, 8, 10, 3, 7); Weight//Key name corresponds to value and weight $count = count ($w); $k = 0; $m =0;for ($i = 0; $i < $count; $i + +) {for ($s = 1; $s < $count; $s + +) {// $s for step $sumw[$k] = $w [$i];   Total weight $suma[$k] = $a [$i];   Total value $road[$k] [] = $i; Save path for ($m = 0; $m < $count; $m + +) {for ($j = $s; $j < $count; $j + +) {if (In_array ($j, $road [$k])) {continue;} $SUMW [$k] + = $w [$j];if ($SUMW [$k] <= $sw) {$road [$k] = $j; $suma [$k]+= $a [$j];} else {break;}}} $k + +;}} Arsort ($suma), $max = current ($suma), $r = Array_keys ($suma, $max), echo "Max:". $max. "
";//Output path: Weight array key Name $RR = 1;foreach ($r as $v) {echo" ROAD ". $rr. ": ". Implode (', ', $road [$v]). "
"; $rr + +;}

Thought I wrote the code, tested is can be implemented, do not understand, can ask questions

max:59
road1:2,4
road2:4,2

The output result is

The others do not consider the problem of step size, and the same weight, the value of different cases are not filtered

Nagging boss didn't see it, the first floor with a poor lifting method, all the combination of first statistics, and then one item to compare to

So to speak, is the method of poor lifting,
Because all scenarios may have m different schemes, but their weight and value ratios are the same,
Do not iterate over all subsets of items, unless you select only one scheme to print the results,

Also, combine quality and value into an array of those answers, see below,

Case One $w = Array (2, 8, 2, 5, 7);  Mass $v  = Array (12, 10, 7, 11, 3);//Value $arr = Array_combine ($w, $v);//$arr result Array (    [2] = 7    [8] = 10
  [5]    [7] = 3)//Condition Two $w = Array (2, 2, 2, 2, 2); $v  = Array (n, a, 7, one, 3); $arr = Array_combine ($w, $v ); Array (    [2] = 3)


Array
(
[2] = 3
)



#16 Floor Answer $p = new Backtracking (Array_values ($w), Array_values ($v), $p->parse (); Echo $p->bestvalue (); $p  Display ();//Condition One $w = Array (2, 2, 2, 2, 7); Mass $v = Array (12, 10, 4, 11, 3);        Value//Result 40Array ([0] = = Array ([w] = 2 [v] = +) [1] = = Array            ([w] = 2 [v] = +) [2] = = Array ([w] = 2 [v] = [3] = = Array ([w] = 2 [v] + 4))//Condition Two $w = Arra  Y (2, 8, 3, 2, 7); Mass $v = Array (12, 10, 7, 11, 3);        Value//Result 30Array ([0] = = Array ([w] = 2 [v] = +) [1] = = Array            ([w] = 2 [v] = +) [2] = = Array ([w] = 3 [V] = 7) [3] = = Array ([w] = 8 [v] = 10))

This post was last edited by xuzuning on 2011-06-10 13:59:22

My #16 code has been updated.

After several sets of data tests, I #16 the code to get a problem with the composition
To be resolved and then to participate in the discussion


$v = Array (2, 4, 6, 8, 10);
$w = Array (1, 2, 3, 4, 5);

$v = Array (1, 2, 3, 4, 5);
$w = Array (2, 4, 6, 8, 10);

To be calculated in terms of value and quality and in proportion, exclude these two cases.

$ar =array (' 1 ' = ' 3 ', ' 4 ' = ' + ', ' 5 ' = ' 3 ', ' 6 ' = ' 7 ', ' 2 ' + ' 9 ', ' + ' = ' 8 ', ' 9 ' = ' 15 ' , ' 6 ');
$a =array ();
$w =10;//Required Weight
foreach ($ar as $key = = $value) {
if ($key <= $w) {$a [$key]= $value;}
}
Print_r ($a);
foreach ($a as $key = = $value) {
$a [$key]= $value/$key;
}
Arsort ($a);
Print_r ($a);
$sum = 0;
$b =array ();
foreach ($a as $key = = $value) {
$sum = $sum + $key;
if ($sum > $w) {break;};
$b [$key]= $ar [$key];
}

Print_r ($b);

$ar =array (' 1 ' = ' 3 ', ' 4 ' = ' + ', ' 5 ' = ' 3 ', ' 6 ' = ' 7 ', ' 2 ' + ' 9 ', ' + ' = ' 8 ', ' 9 ' = ' 15 ' , ' 6 ');
$a =array ();
$w =10;//Required Weight
foreach ($ar as $key = = $value) {
if ($key <= $w) {$a [$key]= $value;}
}
Pri......


Obviously not, and forget to consider if the weight, the value of the same time choice
For example, the required weight is $w=10;
Array (' 2 ' = ' = ' 5 ', ' 2 ' = ' 5 ', ' 2 ' = ' 5 ', ' 2 ' = ' 5 ', ' 2 ' = ' 5 ', ' 5 ' = ' + ', ' 5 ' = ' ' 8 ', ' 15 ' = = > ' 10 ');

Obviously (' 2 ' = ' 5 ', ' 2 ' = ' 5 ', ' 2 ' = ' 5 ', ' 2 ' = ' 5 ', ' 2 ' = ' 5 ') with (' 5 ' = ' + ', ' 5 ' = ' 10 ') is the same

Put this in your program and get it.



$ar =array (' 2 ' = ' 5 ', ' 2 ' = ' 5 ', ' 2 ' = ' 5 ', ' 2 ' = ' 5 ', ' 2 ' = ' 5 ', ' 5 ' = ' + ', ' 5 ' = ' + ', ' 8 ' = ' 15 ', ' 8 ' = ' 10 ');
$a =array ();
$w =10;//Required Weight
foreach ($ar as $key = = $value) {
if ($key <= $w) {$a [$key]= $value;}
}
Print_r ($a);
foreach ($a as $key = = $value) {
$a [$key]= $value/$key;
}
Arsort ($a);
Print_r ($a);
$sum = 0;
$b =array ();
foreach ($a as $key = = $value) {
$sum = $sum + $key;
if ($sum > $w) {break;};
$b [$key]= $ar [$key];
}

Print_r ($b);
?>

The result is an Array ([2] = 5 [5] = 10)

PHP Code

$SW = 15; Backpack weight is 23
$a = Array (2, 3, 44, 5, 15, 12); Value
$w = Array (5, 5, 8, 10, 3, 7); Weight
The key name corresponds to the value and weight
$count = count ($w);
$k = 0;
$m = 0;
for ($i = 0; $i < $count; $i + +) {
......

Not even your code.

$ar =array (Array (1,3), array (3,2), Array (4,8), Array (9,1), Array (11,7), Array (3,12), Array (9,8), Array (7,3));//value 1 means weight, A value of 2 indicates a price
$w = 10;
$a =array ();
$b =array ();
$c =array ();
for ($i =0; $i
If ...

 
  $value) {  $sum = $sum + $a [$key];  if ($sum > $w) {break;};  

The output is an array ([0] = = Array ([0] = 5 [1] = +) [1] = = Array ([0] = 2 [1] = 5) [2] = = Array ([0] = 2 [1] = 5) is the wrong result

The standard answer should be array ([0] = = Array ([0] = 2 [1] = 5) [1] = = Array ([0] = 2 [1] = 5) [2] = = Array ([ 0] = 2 [1] = 5) [3] = = Array ([0] = 2 [1] = 5) [4] = = Array ([0] = 2 [1] = 5))

This post was last edited by xuzuning on 2011-06-10 10:32:06

To facilitate test results, an enumerated first is sent.
Of course, this is not consistent with the landlord requirements
$BK = 15; Backpack $ A = Array (2, 3, 44, 5, 15, 12); Value $w = Array (5, 5, 8, 10, 3, 7); Weight knapsack ($w, $a, $BK), function knapsack ($w, $a, $BK) {  $k = Array_keys ($w);  $r = Array ();  for ($i =1; $i <=count ($k), $i + +) {    $r = Array_merge ($r, combination ($k, $i));  }  foreach ($r as $i = + $t) {    $n = 0;    $v = 0;    foreach ($t as $p) {      $n + = $w [$p];      $v + = $a [$p];    }    if ($n > $bk) unset ($r [$i]);    else {      $MV [$i] = $v;      $MW [$i] = $n;    }  }  Array_multisort ($MW, Sort_desc, $MV, Sort_desc, $r);  foreach ($mw as $i = + $v) {    echo "W: $v v:{$mv [$i]} [";    foreach ($r [$i] as $k) echo "({$w [$k]},{$a [$k]})";      echo "]\n";  }}

W:15 v:56 [(8,44) (7,12)]
W:15 v:30 [(5,3) (3,15) (7,12)]
W:15 v:29 [(5,2) (3,15) (7,12)]
W:15 V:8 [(5,3) (10,5)]
W:15 V:7 [(5,2) (10,5)]
W:13 v:47 [(5,3) (8,44)]
W:13 v:46 [(5,2) (8,44)]
W:13 v:20 [(10,5) (3,15)]
W:13 v:20 [(5,2) (5,3) (3,15)]
W:12 v:15 [(5,3) (7,12)]
W:12 v:14 [(5,2) (7,12)]
W:11 v:59 [(8,44) (3,15)]
W:10 v:27 [(3,15) (7,12)]
W:10 V:5 [(10,5)]
W:10 V:5 [(5,2) (5,3)]
W:8 v:44 [(8,44)]
W:8 v:18 [(5,3) (3,15)]
W:8 V:17 [(5,2) (3,15)]
W:7 V:12 [(7,12)]
W:5 V:3 [(5,3)]
W:5 V:2 [(5,2)]
W:3 v:15 [(3,15)]
  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.