ボクシング問題と石渡り問題に対する私の解決策 http://www.oschina.net/question/117304_112681 を参照してください
主な実装アイデアは次のとおりです: 1. 大きな石は最初に梱包する必要があります (早めにロードし、後で保留する) ) 後の項目はすべて梱包する必要があるので、最初に解決してください) 2. w に近い重量のアイテムを優先して梱包します。 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 )
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 ] => 配列 ( [0] => 8 [1] => 4 [2] => 3 )
[2] => 配列 ( [0] => 7 [1] => 6 [2] => 2 )
)
- // PHP演習ボクシング問題
- // 著者: mx (http://my.oschina.net/meikaiyuan)
- // 2013/5/30
- // 質問:
- / / http://www.oschina.net/question/117304_112681
- /*
- タイトル:
- 以前にも同様の質問をしたことがありますが、良い答えがありません。そこでもう一度聞きたいのです。
- 大小の石の山があり、ボートで川の反対側まで引っ張る必要があります
- -- m 個の石があり、それぞれの重さはわかっています
- -- ボートで運ぶことしかできません一度に k 個の石を積み込みます。積載重量は w
- を超えることはできません -- すべての石を川を渡って運ぶことができる最小往復回数を知りたいです。
- ------------------------------------
- 例 1
- 9 つの石があり、その重さは1,2,3,4,5,6,7,8,9
- k=3
- w=15
- 結果としては、少なくとも3回は発送できることになります。
- ------------------------------------
- 例 2
- 9 つの石があり、それぞれの重さは 1 です。 1,1,5,6,6,7,9,9
- k=3
- w=15
- その結果、出荷が完了するまでに少なくとも 4 回かかります。
- */
- //コードの始まり
- //Stones
- global $rocks;
- //船が一度に積み込める最大個数
- global $k;
- //船の最大積載量
- グローバル $w;
- $k =3;
- $rocks=array(1,2,3,4,5,6,7,8,9);
- // $rocks=array(1,1,1, 5,6,6,7, 9,9); //このデータセットに変更して結果を試してみますか?
- $w=15;
- // 現在何回出荷されていますか?
- $count=0;
- // 輸送プロセス、1=>array(9,5, の形の 2 次元配列) 1) 出荷された回数を示します 運が良かったでしょうか?
- $process=array();
- // 配列 $rocks 内で最大 $k 個の要素と次の合計が存在する組み合わせを見つけます。これらの要素は可能な限り大きく、指定された値 $w 以下です。配列は大きいものから小さいものに並べ替えられています
- function getMaxCombination( ) {
- //Stones
- global $rocks;
- //いくつ船は最大で何個まで運ぶことができますか? global $k;
- //船の最大積載量
- global $w;
- // すべての要素の合計が以下である最大のセットを保存しますw の中で最も大きい値です
- $k_w_result=array();
- // 組み合わせの最大値
- $max_sum=0;
- // どの項目が最大ですか
- $max_one=0 ;
-
- for ($start=$k; $start>0;$start--){
- // 固定の $start 要素で構成される最大解を求めます
- $start_w_arr = getMaxCombination2($start);
- echo "$start 要素で構成される最大解を求めます: n";
- print_r($start_w_arr);
- echo "n";
- $sum=array_sum( $start_w_arr );
- // 注: $k- - は降順に並べられているため、同じ和を持つ $k の組み合わせが早いほど、が見つかると、それが大きいほど、つまりより良い解となるため、
- if($sum>$max_sum){
- $max_sum=$sum;
- $max_one=$k 以下になります。 -$start;
- }
- $k_w_result[]= $start_w_arr ;
- }
- return $k_w_result[$max_one];
- }
-
- // 配列 $rocks 内の指定された $start 要素の組み合わせを見つけます。要素は可能な限り大きいですが、指定された値 $w 以下です。配列は大きい順に並べ替えられています
- function getMaxCombination2($start) {
- //rocks
- global $rocks;
- //船が一度に積み込める石の最大数 Block
- global $k;
- // 船の最大積載量
- global $w;
-
- if(count($rocks)<$start){
- return array(0);
- }
- $c=count($rocks );
- // ループ コードの $start 層を含む関数を $start に基づいて生成し、それをインクルードしてこの関数を呼び出します
- if(!file_exists ( "$start.php")){
- $output_1="";
- $output_2='$sum=';
- $output_3='if($sum<=$w){ $arr=array(); ;
- $output_4='';
- for($i=0;$ i<$start;$i++){
- $output_1.='for($p'.$i.'='.$i.'; $p'.$i.'<$c-'.($ start-$i-1).';$p'.$i.'++){'."n";
- if($i> ;0){
- $output_2.='+';
- }
- $output_2.='$rocks[$p'.$i.']';
- $output_3.='$arr[]=$rocks[$ p'.$i.'];';
- $output_4.=' }';
- }
- $output_2.=';';
- $output_3.=' return $arr; }' ;
- $output='< ;?php 関数 myfor'.$start.'($rocks,$c ,$w){ '.$output_1.$output_2.$output_3.$output_4 .' } ?>';
-
- file_put_contents("$start .php",$output);
- include_once "$start.php";
- }
- else{
- include_once "$start.php";
- }
- return call_user_func('myfor'.$start ,$rocks,$c, $w);
- }
-
- //計算を開始します
- //最初に配列を大きいものから小さいものに並べ替えます。この操作は、後続のアルゴリズムで時間と労力を節約するための鍵です
- rsort($rocks);
-
- //石が大きすぎてボートが小さすぎる場合に、次のアルゴリズムが無限ループを引き起こすのを防ぎます
- foreach ($rocks as $v){
- if($v>$w){
- die("石を積んだ船で、また大きな船で戦いましょう!」 ");
- }
- }
-
- //アルゴリズム開始
- while(!empty($rocks)){
- // 船の積み込み開始
- $process[$count]=array();
-
- // 船の積み込み
- $process[$count]= getMaxCombination( ) ;
-
- // 出荷された
- をrocksから削除 foreach($process[$count] as $v){
- $key=array_search($v, $rocks) ;
- unset( $rocks[$key]);
- }
- $rocks=array_values($rocks);
- // 出荷数 + 1
- $count++;
- }
- // 出力結果
- echo '最小回数:' .$count. "n";
-
- echo '発送プロセス:';
- print_r($process);
-
- ?>
-
コードをコピー
|