• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:計算の法則について)

計算の法則について

このQ&Aのポイント
  • 計算の法則について詳しく調査しました。1setと2setの場合の計算式を作りたいと思っています。aの数量を最小に抑えて、xとyを取りたいです。
  • xとyの範囲は200から1800までで、それぞれ+30で計算します。1setの場合はxとyが2本必要であり、2setの場合はxとyが4本必要です。
  • 考えた方法としては、xとyが長い方からできるだけ取り、余った分から残りの短い方を取るようにしました。ただし、400と500で2setの場合には3本と計算されることがありましたが、これは法則には当てはまりませんでした。VBで計算式を作成していますが、他に法則があるのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

以下の方法はどうでしょうか? 最適解が見つかるわけではありません。 まず、問題をすっきりさせましょう。+30の部分は本質的ではないので、それを加味して、 必要な2つの長さをx,yとします。必要な数をnx,nyとします。取り出す元の材料(?)の長さをaとして、必要な材料数Nを最小にする。 1.準備段階  1つのaから取り出せる最大のx,yの数の組を(i,j)のパターンをすべて求めておきます。  例ではx=530、y=430,a=2000なので、(3,0),(2,2),(1,3),(0,3)の4パターンです。  パターンに番号をつけてPk=(kx,ky)と書くとします。パターンkを選んで取り出すと、xがkx個、yがky個作れることを表します。 2.貧欲アルゴリズム  (1)x,yの必要数が(nx,ny)で与えられる。N=0  (2)全パターンについて以下の計算を行う。     dk = min(nx,kx)+min(ny,ky)  (3)(2)でdkがもっとも大きかったパターンkを採用 複数合った場合はどちらでも可。  (4)必要数(nx,ny)を(max(nx-kx,0),max(ny-ky,0))で置き換える。 maxは負のとき0にするため。  (5)必要数が(0,0)なら終了。そうでなければ(2)へ 例 (nx,ny)=(3,5) とします。 1回目  d1=min(3,3)+min(5,0)=3  d2=min(3,2)+min(5,2)=4  d3=min(3,1)+min(5,3)=4  d4=min(3,0)+min(5,3)=3  パターン2を採用 (nx,ny)は(3,5)→(1,3)に置き換わる。 2回目  d1=min(1,3)+min(3,0)=1  d2=min(1,2)+min(3,2)=3  d3=min(1,1)+min(3,3)=4  d4=min(1,0)+min(3,3)=3  パターン3を採用 (nx,ny)は(1,3)→(0,0)に置き換わる。 終了 結局2枚必要

whitebunny2
質問者

お礼

回答ありがとうございます^^ 難しいですねぇ(汗 でもしたい事は出来そうな気がするので、じっくり考えて理解したいと思います! また質問する事があった時はよろしくお願いします。

その他の回答 (2)

  • DJ-Potato
  • ベストアンサー率36% (692/1917)
回答No.3

VBAを使わずに、関数だけで作ってみました。 本当の最適解であるかはわかりませんが、とにかく端切れを短くすればいいだろう、という計算アルゴリズムなので、大きくは違わないと思います。 関数を記入します。 A1~D2までは、X・Y・aとマチの長さを入力します。 C列は C6 =A6*($A$2+$D$2)+B6*($B$2+$D$2) C7 =A7*($A$2+$D$2)+B7*($B$2+$D$2) : : F3とF4は、最終的に欲しいXとYの本数を入力します。 F列 F6 =IF(OR($C6>$C$2,F$3<$A6,F$4<$B6),0,$C6) F7 =IF(OR($C7>$C$2,F$3<$A7,F$4<$B7),0,$C7) : : G列 G6 =IF(AND(F6<>0,MAX(F$6:F$29)=F6),1,0) G7 =IF(AND(F7<>0,SUM(G$6:G6)=0,MAX(F$6:F$29)=F7),1,0) : : H3 =F3-SUMPRODUCT($A6:$A29,G6:G29) H4 =F4-SUMPRODUCT($B6:$B29,G6:G29) H列I列はF列G列をコピペ J列K列はH列I列をコピペ : : : アルゴリズムの解説です。 A列とB列で、Xをn本とYをm本取る時に、全部でnX+mYの長さが必要で、これをC列に表示しています。 そのうち、C2の値「a」を超えるものは無視、nとmが必要数(F3とF4)を超えるものは無視するので0と変換して 残ったもののうちで一番長いもの(=端切れが一番短いもの)を採用 G列で1になったヤツ ちなみに一番長いものが複数あると困るので、重複したらリストの一番上のヤツを採用するよう手を加えております。 H3H4では採用の分だけF3F4から必要数を引いて表示 以下同様に端切れをとにかく短く取っていきます。 どうでしょう。

whitebunny2
質問者

お礼

関数で出来るとは考えもしなかったです。 とても参考になりました! サンプルまで作って頂き、ありがとうございます。 また質問した時にはお願いします^^

  • DJ-Potato
  • ベストアンサー率36% (692/1917)
回答No.1

2x+2y+120≦1000の時、1セットでも2セットでも1本で済みます。 2x+2y+120≦2000の時、1セットは1本、2セットなら2本で済みます。 (530+530+430+430)×2とすれば2本で済むところを、長い方から出来るだけ取るプログラムのために (530+530+530) 530は取れない 430も取れない (530+430+430+430) 430は取れない (430) と3本消費したワケですね。 1本からXXXXYYYYと並べて取るのではなく、 -XXXXYYYY-を円形に配置して、そこから2000以内でもっとも長く取れる場所を切り出してまずaを1本、という方向にすれば、いくらか解決するでしょうか。

whitebunny2
質問者

お礼

なるほど、円形とは考えつかなかったです。 VBAで可能(VBA初心者なので)かどうか考えてみます! ありがとうございました^^