箱を絞り込む所までは思いつきましたので一応書いておきます
1.全商品が絶対に収まらない箱を除外する
これは単純に各商品の容積を計算しそれに個数をかけたものと
箱の容積を比較すれば分かると思います
全商品の商品の容積を箱の容積が下回れば
その箱に入るという事はありません
ただし
逆に箱の容積が全商品の容積を上回ってさえいれば
必ず収まるとは言えません
2.全商品が必ず収まる「最小の箱」を求める(アルゴリズムA)
2つの商品のサイズ縦横高さを大きさ順にソートして
各順位同士を比較することでどちらかの商品サイズに
もう一つが収まるか否かという事が分かります
これを利用して例えば下記のように3つの商品がある場合
商品A 100 120 70
商品B 110 50 110
商品C 90 80 100
これをソートします(ここでは昇順にソートします)
(商品A 100 120 70 は 70 100 120 となります)
商品A 70 100 120
商品B 50 110 110
商品C 80 90 100
これを縦列で見ていくと
全商品が必ず1個は収まる「最小の箱」は
80(70 50 80で最大)
110(100 110 90で最大)
120(120 110 100で最大)の組合せとなります
3.「最小の箱」を使って全商品が収まるかどうか検討
まずある直方体の中にもう一方の直方体が
最大何個収まるのか決定するアルゴリズムを考えます(アルゴリズムB)
ある向きの直方体A(サイズa×b×c)が
もう一つの直方体B(サイズx×y×z)の中に何個収まるかは
切り捨てをする関数floor( )を使って下記の式で求められると思います
floor(x/a)*floor(y/b)*floor(z/c)
箱の向きは6通りあるので残りの個数も求めます
floor(x/a)*floor(y/c)*floor(z/b)
floor(x/b)*floor(y/a)*floor(z/c)
floor(x/b)*floor(y/c)*floor(z/a)
floor(x/c)*floor(y/a)*floor(z/b)
floor(x/c)*floor(y/b)*floor(z/a)
これらの中で最大値となるのが収まる直方体の最大値です
これを利用してまず「最小の箱」に収まる商品ごとの最大の個数を求めます
商品ごとの最大の個数が求まったら
それに応じた全商品を納めるための「最小の箱」の個数を求めます(アルゴリズムC)
例えば最大の個数が 商品A 1個 商品B 2個 商品C 4個だとすると
商品の個数がそれぞれ(A 5,B 6,B 7)個だったとして
切り上げをする関数ceil()を使って
ceil(5/1) + ceil(6/2) + ceil(7/4)
となり
5 + 3 + 2 となり
全商品を納めるためには10個の「最小の箱」が必要になると思います
必要な「最小の箱」の数が求まったら
それがおさまるものを箱のリストの中から探索します
(やり方は商品が「最小の箱」に何個収まるのか求めたのと全く一緒です)
4.無駄無く納めるために組合せを考える(アルゴリズムD)
必要な容積最小の箱と「最小の箱」が収まる最小の箱の間に
求める箱はあるのだと思いますが
これを探索するのは箱同士の立体的な組合せを考えなければならず
普通に組合せで解こうとすると商品が2・3個のうちは良いが
10個を越えるとお手上げとかそんな類いの問題のような気がします
多分この問題はNP完全かNP困難かといった問題であり
ヒューリスティックに解くしか無く
厳密解は出てこないと予想します
(あくまで予想で証明はできないのですが)
「直方体 充填 アルゴリズム」とかで検索すると
良いものが見つかるかもしれません
※イメージしやすいように図をつけました
文字だけだとわかりにくいですよね
