1. 程式人生 > >動態規劃之背包問題實現php

動態規劃之背包問題實現php

動態規劃 背包問題php

最近在研究動態規劃算法,剛好看到背包問題。看到網上講解這方面問題很多,感覺都有點不明白,後面細思苦想好久,終於理解這個思路。於是寫下個人見解以及解題思路。


背包問題描述如下:

有編號分別為a,b,c,d,e的五件物品,它們的重量分別是4,2,6,5,3,它們的價值分別是6,3,5,4,6,現在給你個承重為10的背包,如何讓背包裏裝入的物品具有最大的價值總和


對於這題我們先不解題。先扯扯動態規劃,下面描述的不太詳細,可以自行百度:


動態規劃所處理的問題是一個多階段決策問題,一般由初始狀態開始,通過對中間階段決策的選擇,達到結束狀態。這些決策形成了一個決策序列,同時確定了完成整個過程的一條活動路線(通常是求最優的活動路線)。動態規劃的設計都有著一定的模式,一般要經歷以下幾個步驟。

初始狀態→│決策1│→│決策2│→…→│決策n│→結束狀態


解題公式:f(n,m)=max{f(n-1,m), f(n-1,m-w[n])+P(n,m)}


這個一開始肯定是懵懂的,不要被這些公式和概念嚇到。現在我們開始解題:

1.首先是初始狀態。 假如只有a物品假如包重量為1-10分別能裝多大價值物品

物品重量價值12345678910
a4
60006666666


因為此時只算上了一個a物品,包各個重量的最大價值已經算出來了。這就是動態規劃的初始狀態。


2. 中間各種決策。上一步得到了只有a物品的情況下包各個重量下的最大價值,現在我們來決策1,就在第一步基礎上增加b物件,現在我們有2個物品,再看看包各個重量的最大價值

物品重量價值12345678910
a460006666666
b230336699999

這裏b4詳細計算的。根據上面2個公式我只用取2個值的最大值。這2個值分別為a4和a(4-2(b的重量))+3(b的價值)。計算後分別為6和3,我們取最大值6。這步是所有理解的關鍵。


於是我們有決策2(同樣的方式將c物品放進來計算),決策3(將d物品放進來),決策4(將e物品放進來)


3.走完所有決策後,於是我們有最終方案了,包各個重量的最大價值即為最後將e物品放進來的那一行。


理論說完我們直接上代碼,這裏是php版本代碼,看了下網上例子,幾乎很少有php版本的代碼,感覺有點歧視php。作為多年php開發經驗,再加上php畢竟世界上最好的語言,哈哈。開個玩笑!

<?php

//初始化各個物品重量和價值數組
$weight_arr = array(0,4,2,6,5,3);
$value_arr = array(0,6,3,5,4,6);

//設置包最大重量為10
$bag_max = 10;
$items = count($weight_arr) - 1;

$cache_map = array();
$cache_map[] = array_fill(1, $items, 0);
$ik = 1;
//初始狀態,假如只有第一個物品包各個重量的最大價值
for($i = 1; $i <= $bag_max; $i++)
{
    if($weight_arr[$ik] > $i) 
    {   
        $cache_map[$ik][$i] = 0;
    }   
    else
    {   
        $cache_map[$ik][$i] = $value_arr[$ik];
    }   
}
//中間的各種決策(依次放入物品b,c,d,e)
for($i = 1; $i <= $bag_max; $i++)
    for($j = 2; $j <= $items; $j++)
    {   
        $j_weight = $weight_arr[$j];
        $j_value = $value_arr[$j];
        $j_prev_value = $cache_map[$j-1][$i];
        if($j_weight > $i)
        {       
            $cache_map[$j][$i] = $j_prev_value;
        }       
        else    
        {       
            $j_extra_value = $j_value + $cache_map[$j-1][$i-$j_weight];
            $cache_map[$j][$i] = max($j_prev_value, $j_extra_value);
        }       
    }   

//最終狀態
for($i = 1; $i <= $bag_max; $i++)
{
    echo $i . ':' . $cache_map[$items][$i] . PHP_EOL;
}


最後顯示下計算結果吧:

1:0
2:3
3:6
4:6
5:9
6:9
7:12
8:12
9:15
10:15


動態規劃之背包問題實現php