php解決裝箱問題

WBOY
發布: 2016-07-25 08:51:00
原創
1179 人瀏覽過
我對裝箱問題,石頭過河問題的解法
見http://www.oschina.net/question/117304_112681

實現思路主要為:
1. 大塊石頭必須優先裝箱(早裝和留到後面裝都要裝,先解決之)
2. 優先裝重量接近w的
3. 同樣重量優先裝多塊,如裝9,6和裝9,5 ,1比,則優先951裝箱
4. 使用php的函數以簡化程式碼,並使用根據k值產生函數的技巧
5. 此類問題由於本身性質,計算量較大,請酌情設定參數測試。

範例輸出:(當rocks為1~9,w為15,k為3)
尋找由3 個元素組成的最大解:
Array
(
[ 0] => 9
[1] => 5
[2] => 1
)

尋找由2 個元素組成的最大解:
Array
(
[0] => 9
[1] => 6
)

找出由1 個元素組成的最大解:
Array
(
[0] => 9
)

尋找由3 個元素組成的最大解:
Array
(
[0] => 8
[1] = > 4
[2] => 3
)

尋找由2 個元素組成的最大解:
Array
(
[0] => 8
[1] => 7
)

尋找由1 個元素組成的最大解:
Array
(
[0] => 8
)
(
[0] => 8
)

尋找由3 個元素組成的最大解:
Array
(
[0] => 7
[1] => 6
[2] => 2
)

尋找由2 個元素組成的最大解:
Array
(
[0] => 7
[1] => 6
)

尋找由1 個元素組成的最大解:
Array
(
[0] => 7
)

最少次數:3
裝裝船過程:Array
(
[0] => Array
(
[0] => 9
[1] => 5
[2] => 1
)

[1] => Array
(
[0] => 8
[1] => 4
[2] => 3
)

[2] => Array
(
[0] => 7
[1] => 6
[2] => 2 ))
  1. // php 練習之裝箱問題
  2. // author: mx (http://my.oschina.net/meikaiyuan)
  3. // 2013/5/30
  4. // 問題:
  5. // http://www.oschina.net/question/117304_112681
  6. /*
  7. 題目:
  8. 以前問過類似問題,沒有很好解答。所以想再問一次。
  9. 有大大小小的一堆石頭要用船拉到河對岸
  10. --石頭有m塊,每塊的重量已知
  11. --船每次只能裝k塊石頭,並且裝載重量不可以超過w
  12. --想求出最少幾趟能把全部石頭運過河。
  13. ------------------------------------
  14. 例1
  15. 石頭有9塊,重量分別是1,2,3,4,5,6,7,8,9
  16. k=3
  17. w=15
  18. 那麼結果是,最少3次就可以運完。
  19. ------------------------------------
  20. 例2
  21. 石頭有9塊,重量分別是1,1,1,5,6,6,7,9,9
  22. k=3
  23. w=15
  24. 那麼結果是,最少4 次才可以運完。
  25. */
  26. //代碼開始
  27. //石頭
  28. global $rocks;
  29. // 船隻每次最多裝幾塊
  30. global $k;
  31. // 船最大載重量
  32. global $w;
  33. $k=3;
  34. $rocks=array(1,2,3,4,5,6,7,8 ,9);
  35. // $rocks=array(1,1,1,5,6,6,7,9,9); //換成這組資料試試看結果?
  36. $w=15;
  37. // 目前運了幾下
  38. $count=0;
  39. // 運輸過程,二維數組,形如1=>array(9, 5,1),表示第幾次運了哪一些
  40. $process=array();
  41. // 求數組$rocks中一組合,使得最多$k個元素且這些元素的和盡可能大但小於等於指定值$w, 數組已經按從大到小排序過
  42. function getMaxCombination( ) {
  43. //石頭
  44. global $rocks;
  45. // 船每次最多裝幾塊
  46. global $k;
  47. // 船最大載重量
  48. global $w;
  49. // 保存各種$k下滿足所有元素總和小於等於w且最大的集合
  50. $k_w_result=array();
  51. // 最大組合值
  52. $max_sum=0;
  53. // 哪一項最大
  54. $max_one=0;
  55. for ($start=$k;$start>0;$start--){
  56. // 找出由固定$start個元素組成的最大解
  57. $start_w_arr = getMaxCombination2($start);
  58. echo "尋找由$start 個元素組成的最大解: n";
  59. print_r($start_w_arr);
  60. echo "n";
  61. $sum=array_sum( $start_w_arr );
  62. //注意:因為是降序排列的,$k--, 越早找到的同sum的組合$k越大,也就是解越好,所以是小於不是小於等於
  63. if($sum>$max_sum){
  64. $max_sum=$sum;
  65. $max_one=$k-$start;
  66. }
  67. $k_w_result[]= $start_w_arr ;
  68. }
  69. return $k_w_result[$max_one] ;
  70. }
  71. // 求數組$rocks中一由給定$start個元素構成的組合,這些元素的和盡可能大但小於等於指定值$w, 數組已經按從大到小排序過
  72. function getMaxCombination2($start ) {
  73. //石頭們
  74. global $rocks;
  75. // 船每次最多裝幾塊
  76. global $k;
  77. // 船最大載重量
  78. global $w;
  79. if(count($rocks) return array(0);
  80. }
  81. $c= count($rocks);
  82. // 根據$start產生一函數,內含$start層for循環程式碼, 然後包含進來再呼叫此函數
  83. if(!file_exists( "$start.php")) {
  84. $output_1="";
  85. $output_2='$sum=';
  86. $output_3='if($sum $output_4='';
  87. for($i=0;$i $output_1.='for($p'.$i.'='.$i .';$p'.$i.' if( $i>0){
  88. $output_2.=' ';
  89. }
  90. $output_2.='$rocks[$p'.$i.']';
  91. $output_3.=' $arr[]=$rocks[$p'.$i.'];';
  92. $output_4.='}';
  93. }
  94. $output_2.=';';
  95. $ output_3.=' return $arr; }' ;
  96. $output='';
  97. file_put_contents("$start.php",$output);
  98. include_once "$start.php";
  99. }
  100. else{
  101. include_once "$start.php";
  102. }
  103. return call_user_func('myfor'.$start ,$rocks,$c,$w);
  104. }
  105. //開始開始計算
  106. // 陣列先從大到小排序, 此操作是後續演算法省時省力的關鍵
  107. rsort($rocks);
  108. // 為了防止石頭過大船過小造成下面演算法死循環
  109. foreach ($rocks as $v){
  110. if($v>$w){
  111. die("有石頭不可能裝船,換大船來再戰! ");
  112. }
  113. }
  114. // 演算法開始
  115. while(!empty($rocks)){
  116. // 開始裝一船
  117. $process[$ count]=array();
  118. // 裝船
  119. $process[$count]= getMaxCombination( ) ;
  120. // 從石頭中移除已經裝船的
  121. foreach($process[$count] as $v){
  122. $key=array_search($v, $rocks);
  123. unset( $rocks[$key]);
  124. }
  125. $ rocks=array_values($rocks);
  126. // 裝船數1
  127. $count ;
  128. }
  129. // 輸出結果
  130. echo '最小次數:'.$count."n" ;
  131. echo '裝船過程:';
  132. print_r($process);
?>
複製代碼


相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板