PHP realizes dynamic programming of 01 knapsack problem

1. First look at this equation, which is the essence of the knapsack problem

01 The state transition equation of the backpack f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ), f[i-1,j] }

f[i,j] represents the maximum value that can be obtained by selecting several items from the first i items and placing them in a knapsack with a load of j.
Pi represents the value of the ith item.
Decision: In order to maximize the total value of the items in the knapsack, should the ith item be put in the knapsack? This needs to be compared.

2. Problem description

There are n items and a knapsack that can bear the maximum weight c. The weight of item i is wi, and its value is vi. Ask how to choose the items to be loaded so that the total value of the items in the knapsack is the largest. For each item, we can only choose to take or not to take two choices, can not choose to load a part of an item, and can not load the same item multiple times.

3. Examples

There are 5 items a, b, c, d, e, their weights are 2, 2, 6, 5, 4, and their values ​​are 6, 3, 5, 4, 6, and now give one that can bear the weight 10 backpacks.

4. Drawing


What does this picture mean? A little introduction. First of all, it must be clear that this table is generated from bottom to top and from left to right.

For the convenience of description, the cell e2 is used to represent the cell in row 2 and column e. This cell means that when there is item e, there is a backpack that can bear a load of 2, then the maximum value of this backpack is 0, because item e The weight is 4, and the back pack can't fit.

For cell d2, it means that when the item has e and d, there is a backpack with a load-bearing capacity of 2, and the maximum value that can be loaded is still 0, because neither e nor d can be loaded by this backpack.

Then for a backpack with a load-bearing capacity of 8, a8=15, how to understand this?

According to the state transition equation of the 01 backpack, two values ​​need to be examined, one is f[i-1,j], which is the value 9 of b8 for this example, and the other is f[i-1,j-Wi]+ Pi; here, f[i-1,j] means that I have a backpack with a load-bearing capacity of 8. When only four items b, c, d, and e are available, the maximum value f[i of this backpack can be loaded into -1,j-Wi] means that I have a backpack with a load capacity of 6 (equal to the current backpack load capacity minus the weight of item a), when only four items b, c, d, and e are optional, this backpack can be loaded The maximum value of f[i-1,j-Wi] refers to cell b6, the value is 9, and Pi refers to the value of item a, that is, since f[i-1,j-Wi]+Pi = 9 + 6 = 15 is greater than f[i-1,j] = 9, so item a should be put into a backpack with a load capacity of 8.

The simple understanding is to compare the value of the current item I put in and the value of the current item without it. Whichever value is greater, I will take which method.

It is recommended that the above picture be drawn by hand to facilitate understanding.

5. Code section

// f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ),  f[i-1,j] }
// The backpack can hold the maximum weight
$w=10;
//There are four items here, the weight of each item
$dx=array(2,2,6,5,4);
//value of each item
$val=array(6,3,5,4,6);
//define an array
$maxValue=array();
//initialization
for($i=0;$i<=10;$i++){
    $maxValue[0][$i]=0;
}
for ($j=0;$j<=5;$j++){
    $maxValue[$j][0]=0;
}
//Max{ f[i-1,j-Wi]+Pi( j >= Wi ),  f[i-1,j] }
for ($j=1;$j<=5;$j++){
    for($i=1;$i<=10;$i++){
        $maxValue[$j][$i]=$maxValue[$j-1][$i];
        //Not greater than the largest w=10
        if($dx[$j-1]<=$w){
            //This situation is to prevent it from becoming a negative number after subtracting its own weight
            if(!isset($maxValue[$j-1][$i-$dx[$j-1]])) continue;
            //f[i-1,j-Wi]+Pi( j >= Wi )
            $tmp = $maxValue[$j-1][$i-$dx[$j-1]]+$val[$j-1];
            //Max{ f[i-1,j-Wi]+Pi( j >= Wi ), f[i-1,j] } => for comparison
            if($tmp>$maxValue[$j][$i]){
                $maxValue[$j][$i]=$tmp;
            }
        }
    }
}
//Print this array, output the value in the far right corner is the maximum value
for ($j=1;$j<=5;$j++){
    for ($i=1;$i<=10;$i++){
        if ($maxValue[$j][$i]<10)
        echo " ".$maxValue[$j][$i]." ";
        else echo $maxValue[$j][$i]." ";
    } echo "<br>";
}
The summary blog is from http://blog.csdn.net/mu399/article/details/7722810


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325938993&siteId=291194637