質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

解決済

6回答

3114閲覧

最適な組み合わせの巻数を動的に算出するアルゴリズム

Kazu9999

総合スコア11

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

2グッド

8クリップ

投稿2018/08/29 02:36

編集2018/08/29 05:36

前提・実現したいこと

現在、設計中の業務システムで扱ってる商材で、数m巻にまかれた生地があります。
それを必要な長さと枚数で、どう動的に最安の組み合わせになるかというアルゴリズムに苦戦しております。
ナップザック問題や、欲張り法など調べてますが、どうも今回のパターンにうまく当てはめることができません。

その生地は、以下のような特徴があります。
1ロールあたりの巻数の種類 : 12m巻き 30m巻き (これは生地によって変わりますので例です。)
それぞれの原価
12m巻 8,000円
30m巻 19,000円
※ 巻数が大きいものの方がm単価は安くなります。

例えばお客様から、長さ5.5mの生地を20枚ほしいと注文があった場合、
12m巻の生地を長さ5.5mづつカットすると、作成可能枚数は、2枚で、0.5m 端生地が余ります。
30m巻の生地を長さ5.5mづつカットすると、作成可能枚数は、5枚で、2.5m 端生地ります。

上記の中から最も金額を安くする最適な巻数の組み合わせを動的に算出する計算式になります。

例えば、いくつか例です。

長さ5mを5枚必要な場合
パターン① 12m巻でまかなうと、3ロール必要、8,000円x3ロール=24,000円
パターン② 30m巻でまかなうと、1ロール必要、19,000円x1ロール=19,000円

 この場合は、パターン②の30m巻を1ロール購入するのが正解です。

長さ5mを7枚必要な場合
パターン① 12m巻のみでまかなうと、4ロール必要、8,000円x4ロール=32,000円
パターン② 30m巻のみでまかなうと、2ロール必要、19,000円x2ロール=38,000円
パターン③ 30m巻と12m巻でまかなうと、30m巻1ロール、12m巻1ロール= 8,000円+19,000円=27,000円

 この場合は、パターン③の30mと12mを組み合わせるパターンが最も安くなります。

このような動的で最適なパターンの算出を行うために、どのような方法がありますでしょうか。
どうかお知恵を貸してください。

denjiry, set0gut1👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2018/08/29 04:04 編集

>12m巻 8,000円 30m巻 22,000円 ※ 巻数が大きいものの方がm単価は安くなります。 なってないのでは?
sazi

2018/08/29 04:07 編集

余った端数は利用しないの? まあ、それは実際に裁断するときに考えればいいのか
Kazu9999

2018/08/29 04:19

すみません、仮で入れた価格が間違っておりました。実際はm単価はやすくなります。
Kazu9999

2018/08/29 04:21

余った端生地は、今は捨ててます。本来なら、余った生地の在庫管理も行って効率化すればいいのですが、今後の課題です。
sazi

2018/08/29 05:04

料金設定間違えてるなら質問も変えないとおかしくなりませんか?安い高いの話をしてるんですから
Kazu9999

2018/08/29 05:30

すみません、質問を修正しました。
sazi

2018/08/29 05:32

例の部分がまだですよ
sazi

2018/08/29 06:41

M単位の単価は関数が大きいほうが安いけど、24M以下だと12巻の方が安いのね。
yukihisa

2018/08/29 06:56

割引的には5%引き程度、と言ったところですね。
guest

回答6

0

巻き数の種類っていうのが2種類とは限らなさそうなので次のように一般化します。

  • お客様から長さ T メートルの生地を N 枚ほしいと注文がある。
  • 巻数の種類は K 種類存在し、それぞれ L[i] メートル C[i] 円とする。(i = 0 〜 K-1)

端生地は単純に捨てるとすると、1ロール何枚と見なせて、ちょっと単純化できます。

  • 巻数の種類は K 種類存在し、それぞれ M[i] 枚 C[i] 円とする。

動的計画法を用いて最安値を算出する処理を書くと、次のようになります。

  • i 枚とるための最安値 A[i] を 1〜N にかけてボトムアップで計算する
  • A[0] = 0 (i < 0 のときも A[i] = 0 とみなす)
  • A[i] = min( 巻数の各種類 j に対して A[i-M[j]] + C[j] )

計算量は O(N*K) となります。

最安値しか求めてないですが、どのロールを何個っていう情報も要ると思うので、適宜構造体かなにかで A[i] に保存してください。

■例:

次のようなパラメータだとします。

  • お客様から長さ5.5mの生地を20枚ほしいと注文があった場合
  • 12m巻(2枚) 8,000円
  • 30m巻(5枚) 19,000円

20枚取るための最安値は次のいずれかで、

  • 18枚の最安値 + 8000
  • 15枚の最安値 + 19000

この操作を 1 から N までボトムアップでやる感じになります。

投稿2018/08/29 03:49

編集2018/08/29 09:02
set0gut1

総合スコア2413

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Kazu9999

2018/08/29 05:12

ありがとうございます! なるほど、1枚あたりで換算するとわかりやすくなりますね。 熟考して理解してみます。
swordone

2018/08/29 05:41

逆方向に考えれば、動的計画法で行けそう。
set0gut1

2018/08/29 05:52

すみません回答のアルゴリズム改善しました。枚数が増えて最安値が減少することが無いことは保証されるので、20枚のことを考えるときに 15+5枚 のことだけを考えればよく、16+5枚 〜 19+5枚 のことは考えなくて良かったです。
swordone

2018/08/29 16:02

2種類のロールでどっちも偶数枚取れるときに奇数枚必要な処理が難しくなるから、枚数オーバーは取っておいていいのではないだろうか。
guest

0

ベストアンサー

まず数式化

必要な長さをaとすると
1巻ごとの余りの長さはそれぞれ12%am、30%a
これが1巻ごとに無駄になるので、実際使える長さはそれぞれ12 - 12%am、30 - 30%a
1巻あたり作成できるのが、(12 - 12%a)/a枚、(30 - 30%a)/a枚。
必要枚数をbとすると、金額はa * b / (12 - 12%a) * 8,000a * b / (30 - 30%a) * 19,000(必要枚数÷1巻当たりの枚数*金額。それぞれ単体時、余ったときには別に処理しないといけないので端数切捨て)
端数(余り枚数)はb % (12 - 12%a) / ab % (30 - 30%a) / a

大前提として、基本的に30mのほうが安いのでそちらを使用する。

最初にa * b / (30 - 30%a) * 19,000を端数切捨てで計算し、
次にb % (30 - 30%a) / a = cで端数分の枚数を算出する。
a / (12 - 12%a) * c < 3(12mを買ったほうが安い)の場合、12mを選んだほうが安いので、a / (12 - 12%a) * c * 8,000を端数切り上げで計算して金額に足す。
a / (12 - 12%a) * c >= 3の場合は30mを買ったほうが安いので計算結果に19,000(30m1巻分)を足す。
という形でしょうか。

んー、表現の仕方が難しい。

追記

割引率を良く見ていなかった。。。
割引率によって(30*30mの単価/12mの単価)m未満かどうか切り分けないといけない(たとえば3割引なら21m未満)ですね、失礼しました。
さらにその中できちんと何巻取れるか計算しなきゃいけないですね。

追記の追記。
とりあえず金額を修正した値にしました。

プログラミングでの表現

とりあえず、すぐ見られるのでcodepenで作成(javascript) (8/30 修正しました。)
注文数最安値計算テスト
レイアウト等は適当なのでご容赦を。
初期値は質問で提示されているもので、エラーが起きそうなもの。テキストボックス内を自由に変更してテストできます。
※修正前は5.5mを16枚が30x3、12x1にの計65,000円になっていました。
修正後は30x2、12x3の計62,000円になり最安値になっております。

アルゴリズム。

前提として、単価の安い大きいものから選択する。 ⇒ kan1
余りが出る長さになったら、一つ小さいものを選択する。 ⇒ kan2
余りが出た場合、余りの大きさによって大きいもの一巻よりも小さいもの複数の方が安くなる場合があるため、余り枚数+大きい物1巻当たりの枚数で計算をする。 ⇒ kan3
計算の結果、kan3小さいものの金額 < 大きいものの金額+小さいものの金額の場合、小さいもの複数の方が安いためkan1で出した結果を-1し、kan2にkan3を代入する。
kan2
小さいものの金額 > 大きいものの金額になった場合、余りが出ても大きいものの方が安いので小さいものは使用せずにkan1に+1する。
大きいものをkan1巻、小さいものをkan2巻が最安値になる。
種類が増える場合はこれを繰り返せばいけるはず。

投稿2018/08/29 03:00

編集2018/08/31 00:49
yukihisa

総合スコア672

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/08/29 13:35

できるだけロールが長い方を使っていく作戦だと、15m巻: 1501円、25m巻: 2500円のロールを使用して5mの生地を6枚取る場合に、15m+15m (3002円)ではなく 25m+15m (4001円)という解になってしまいませんか?
yukihisa

2018/08/30 00:10

むむ、なるほど。 ということは前提を「余りが最小且つ巻数が最小」に変更しなくてはいけないですね。 仕様漏れ申し訳ない。
yukihisa

2018/08/30 01:06

修正いたしました。 そもそもはじめに入っている5.5x16の時点で最安値じゃなかったという。。。 ご指摘感謝です。
guest

0

12m -> 8000円
30m -> 19000円という条件で 7m * 3の注文の場合について具体的に説明します。

まず、最初に12mだけだと何巻きいるのか30mだけだと何巻いるのかそれぞれ計算します。
(一番下にある私がかいたソースコードだとメソッドhow_many)
それぞれ必要な巻き数をa,bとします。今回だとa = 3, b = 1です。
合計金額の最小値をa * 8000円と初期化します。(今回はmin = 3 * 8000 = 24000)
.for文で変数iを0~3まで回します。(12mを使う巻数の最小値から最大値まで)
この際、12mを使った個数に応じて30mがいくつ必要か求めます。
例えば、12mが1つだと30mは1つになります。これもメソッドhow_manyで求まります。
それぞれの必要な巻数がわかるので合計金額が算出できます。
.for文で回しながら合計金額の最小値を求めます。
一応,計算の途中過程をコメントアウトしています。

なお、今回は準備されているものの種類が12m,30mの二つで注文する長さと個数は自然数のときだけを考えています。
種類を増やしたいときはint []basic_length = {12,30};を変更してください。
それと同時にint []price = {8000,19000};も変更する必要があります。

java

1import java.util.*; 2 3public class Main { 4 public static void main(String[] args){ 5 6 Scanner sc = new Scanner(System.in); 7 System.out.println("何mをいくつ注文しますか?"); 8 System.out.println("長さ->"); 9 int length = sc.nextInt(); 10 System.out.println("巻数->"); 11 int num = sc.nextInt(); 12 13 int []need_num = new int[2]; 14 int []basic_length = {12,30}; 15 int []price = {8000,19000}; 16 for(int i = 0; i < 2; i++){ 17 need_num[i] = how_many(basic_length[i],length,num); 18 //System.out.println(need_num[i]); 19 } 20 int min = need_num[0] * price[0]; 21 //System.out.println("min = " + min ); 22 int total_price = 0; 23 int []result_num = new int[2]; 24 for(int i = 0; i <= need_num[0]; i++){ 25 int tmp = how_many(basic_length[0],length,i); 26 int tmp2 = how_many(basic_length[1],length,num - i); 27 total_price = tmp * price[0] + tmp2 * price[1]; 28 //System.out.printf("%d = %d ,%d = %d %d \n",basic_length[0],tmp,basic_length[1],tmp2,total_price); 29 if(total_price <= min){ 30 min = total_price; 31 result_num[0] = tmp; 32 result_num[1] = tmp2; 33 } 34 } 35 for(int i = 0; i < 2; i++){ 36 System.out.printf("%dmが%d巻 ",basic_length[i],result_num[i]); 37 } 38 System.out.printf("合計%d円になります.\n",min); 39 40 } 41 public static int how_many(int basic_length,int order_length, int num) 42 { 43 int tmp = basic_length / order_length; 44 int need_num = 0; 45 while(tmp * need_num < num){ 46 need_num++; 47 } 48 return need_num; 49 } 50} 51

<実行結果>
何mをいくつ注文しますか?
長さ->7
巻数->3
12mが0巻 30mが1巻 合計19000円になります.

投稿2018/08/29 13:13

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

複数の組み合わせ及び小数点対応しました。
出力結果はコード内のコメントに残してます。
例題全4パターン出力可能です。
//5x5//5x7//18x2//5.5x20

java

1 2public class memo102 { 3 4 // 例えば、いくつか例です。 5 // 6 // 長さ5mを5枚必要な場合 7 // パターン① 12m巻でまかなうと、3ロール必要、8,000円x3ロール=24,000円 8 // パターン② 30m巻でまかなうと、1ロール必要、19,000円x1ロール=19,000円 9 // 10 // この場合は、パターン②の30m巻を1ロール購入するのが正解です。 11 // 12 // 長さ5mを7枚必要な場合 13 // パターン① 12m巻のみでまかなうと、4ロール必要、8,000円x4ロール=32,000円 14 // パターン② 30m巻のみでまかなうと、2ロール必要、19,000円x2ロール=38,000円 15 // パターン③ 30m巻と12m巻でまかなうと、30m巻1ロール、12m巻1ロール= 8,000円+19,000円=27,000円 16 // 17 // この場合は、パターン③の30mと12mを組み合わせるパターンが最も安くなります。 18 // 19 // このような動的で最適なパターンの算出を行うために、どのような方法がありますでしょうか。 20 // どうかお知恵を貸してください。 21 22 public static void main(String[] args) { 23 24 // a=必要長さ (m) 25 // b=必要枚数 (枚) 26 // c=a*b=合計長さ (m) 27 // d=ロール (m) 28 // e=単価 (円) 29 30 //例題 31 //5x5 32 //5x7 33 //18x2 34 //5.5x20 35 36 // 5m x 5枚必要 37 // 30m巻 x 1ロール = 19000円 38 // 最安値総計19000円 39 40 // 5m x 7枚必要 41 // 12m巻 x 1ロール = 8000円 42 // 30m巻 x 1ロール = 19000円 43 // 最安値総計27000円 44 45 // 18m x 2枚必要 46 // 30m巻 x 2ロール = 38000円 47 // 最安値総計38000円 48 49 // 5.5m x 20枚必要 50 // 12m巻 x 2ロール = 16000円 51 // 30m巻 x 3ロール = 57000円 52 // 最安値総計73000円 53 54 double a = 18; 55 int b = 2; 56 double c = a * b; 57 58 int[] d = { 12, 30 }; 59 int[] e = { 8000, 19000 }; 60 61 int[] ans = func(a, b, c, d, e); 62 int sum = 0; 63 64 System.out.println(a + "m x " + b + "枚必要"); 65 for (int i = 0; i < ans.length; i++) { 66 if (ans[i] != 0) { 67 sum += ans[i] * e[i]; 68 System.out.println(d[i] + "m巻 x " + ans[i] + "ロール = " + ans[i] * e[i] + "円"); 69 } 70 } 71 System.out.println(" 最安値総計" + sum + "円"); 72 } 73 74 static int[] func(double a, int b, double c, int[] d, int[] e) { 75 76 int n = d.length; 77 int x; 78 int[] result = new int[n]; 79 int[][] chk1 = new int[n][2]; 80 81 //最安値単価の商品IDを取得=f 82 int f = 0; 83 for (int i = 0; i < d.length - 1; i++) { 84 if (e[i] / d[i] < e[i + 1] / d[i + 1]) { 85 f = i; 86 } else { 87 f = i + 1; 88 } 89 } 90 91 //最安値単価の商品=fで端数が出るまでまかなう 92 result[f] = (int) (c / ((d[f] / (int) a) * a)); 93 94 //残り長さを端数で更新 95 // c = c % d[f]; 96 97 c -= result[f] * d[f]; 98 99 if(c<0) { 100 return result; 101 } 102 103 //d0 //d1 104 //12 //30 105 //a5 b5 106 //c25 107 108 //d0 //d1 109 //12 //30 110 //a5 b7 111 //c35 112 113 //d0 //d1 114 //12 //30 115 //a18 b2 116 //c36 117 118 //d0 //d1 119 //12 //30 120 //a5.5 b20 121 //c110.0 122 123 //30/5.5=5 124 125 for (int i = 0; i < n; i++) { 126 127 if (d[i] < a) { 128 continue; 129 } 130 131 if (d[i] > c) { 132 chk1[i][0] = 1; 133 chk1[i][1] = e[i]; 134 } else { 135 x = (int) Math.ceil(1.0 * c / d[i]); 136 chk1[i][0] = x; 137 chk1[i][1] = e[i] * x; 138 } 139 } 140 141 int ans = 0; 142 for (int i = 0; i < n - 1; i++) { 143 144 if (chk1[i][1] == 0) { 145 ans = i + 1; 146 continue; 147 } 148 149 if (chk1[i][1] < chk1[i + 1][1]) { 150 ans = i; 151 } else { 152 ans = i + 1; 153 } 154 } 155 156 result[ans] += chk1[ans][0]; 157 return result; 158 } 159} 160

※以下初回分ですがコメント頂いているので残してます。

java

1言語が何か分からないので自分の勉強のために例題としてjavaで実装してみました。 2if文とfor文くらいしか使ってないですが何かの参考になればと思います。 35x5と5x7のケースしかテストしていません。 4 5--- 6 7出力結果 8 95m x 5枚必要 10 111種類でまかなう場合 1212m巻 x 3ロール = 240001330m巻 x 1ロール = 220001460m巻 x 1ロール = 4000015 16 17複数で組み合わせる場合 1812m巻 x 3ロール = 2400019 総計2400020 21--- 225m x 7枚必要 23 241種類でまかなう場合 2512m巻 x 3ロール = 240002630m巻 x 2ロール = 440002760m巻 x 1ロール = 4000028 29 30複数で組み合わせる場合 3130m巻 x 1ロール = 220003212m巻 x 1ロール = 800033 総計3000034 35public class memo102 { 36 37 // 長さ5mを5枚必要な場合 38 // パターン① 12m巻でまかなうと、3ロール必要、8,000円x3ロール=24,000円 39 // パターン② 30m巻でまかなうと、1ロール必要、22,000円x1ロール=22,000円 40 // 41 // この場合は、パターン②の30m巻を1ロール購入するのが正解です。 42 // 43 // 長さ5mを7枚必要な場合 44 // パターン① 12m巻のみでまかなうと、4ロール必要、8,000円x4ロール=32,000円 45 // パターン② 30m巻のみでまかなうと、2ロール必要、22,000円x2ロール=44,000円 46 // パターン③ 30m巻と12m巻でまかなうと、30m巻1ロール、12m巻1ロール= 8,000円+22,000円=30,000円 47 // 48 // この場合は、パターン③の30mと12mを組み合わせるパターンが最も安くなります。 49 50 public static void main(String[] args) { 51 52 // a b c 53 // a=必要長さ (m) 54 // b=必要枚数 (枚) 55 // c=a*b=合計長さ (m) 56 // 57 // d e 58 // d=ロール (m) 59 // e=単価 (円) 60 61 //例題 62 //5x5 63 //5x7 64 //18x2 65 66 int a = 18; 67 int b = 2; 68 int c = a * b; 69 70 int[] d = { 12, 30, 60 }; 71 int[] e = { 8000, 22000, 40000 }; 72 73 func(a, b, c, d, e); 74 75 } 76 77 static void func(int a, int b, int c, int[] d, int[] e) { 78 int sum; 79 int x; 80 81 System.out.println(a + "m x " + b + "枚必要"); 82 System.out.println(); 83 System.out.println("1種類でまかなう場合"); 84 85 //1種類でまかなう 86 for (int i = 0; i < d.length; i++) { 87 sum = 0; 88 x = 0; 89 90 //追記 91 if(d[i]<a) { 92 continue; 93 } 94 95 if (d[i] >= c) { 96 x = (int) Math.ceil(c * 1.0 / d[i]); 97 sum = x * e[i]; 98 System.out.println(d[i] + "m巻 x " + x + "ロール = " + sum + "円"); 99 } else { 100 101 x = (int) Math.ceil(c * 1.0 / d[i]); 102 sum = x * e[i]; 103 System.out.println(d[i] + "m巻 x " + x + "ロール = " + sum + "円"); 104 } 105 } 106 107 System.out.println(); 108 System.out.println(); 109 System.out.println("複数で組み合わせる場合"); 110 111 //複数で組み合わせる場合 112 sum = 0; 113 x = 0; 114 int tmp[] = new int[d.length]; 115 116 for (int j = d.length - 1; j >= 0; j--) { 117 118 if (d[j] >= c && j != 0) { 119 continue; 120 } 121 122 if(d[j]<a) { 123 continue; 124 } 125 126 127 while (c > 0) { 128 c = c - d[j]; 129 sum += e[j]; 130 tmp[j]++; 131 132 if (c - d[j] < 0 && j != 0) { 133 134 //追記 135 if(d[j-1]<a) { 136 sum += e[j]; 137 tmp[j]++; 138 } 139 140 break; 141 } 142 } 143 } 144 145 for (int i = d.length - 1; i >= 0; i--) { 146 if (tmp[i] != 0) { 147 System.out.println(d[i] + "m巻 x " + tmp[i] + "ロール = " + tmp[i] * e[i] + "円"); 148 } 149 } 150 System.out.println(" 総計" + sum + "円"); 151 } 152} 153

投稿2018/08/29 05:09

編集2018/08/29 11:16
opyon

総合スコア1009

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yukihisa

2018/08/29 05:14

それだと最後の余りの部分でやっぱり長いほうを使わないととかなる場合に対応できない気がします。
opyon

2018/08/29 05:24 編集

5x5と5x7の最安値の正解を出すことを目的に勉強のために作っただけですのですみませんでした。 「長い方の余りを使う」という要件は例題には書かれていないようですが、要件はまだ増えますか? 素人が言うのも何ですが具体的な仕様もう少し出されたほうが回答得られやすいと思いますよ。 @yukihisaさんは質問者さんじゃなかったようですね。失礼しました。
yukihisa

2018/08/29 05:40 編集

あぁ、「最後の余り」というのはたとえば5mを17枚欲しいとなったときに、このコードでは30mで2巻、12mで3巻という計算結果になると思うのですが、単価が12m>30mなので12m3巻買うよりも30mの方が安いという結果になるので、そういった際の処理が抜けているかな、ということでして。 あくまでも質問者様の最初の仕様どおり「最安値」を求めるための部分で、増えたわけではないです。 事実、5x5の時点で30m22,000が最安値なのに12mx3の24,000が返ってきていますし。 そもそも価格設定を間違えてらっしゃるのでどっちが安い!とすぐわからないのが困りものですが。。。
opyon

2018/08/29 06:06 編集

>「最後の余り」 なるほど。単純に5x5や5x7の結果が出た程度では意味ないようですね。 >30m22,000が最安値なのに 出力結果に一応出てます >価格設定を間違えて >すぐわからない 複数商品があるとのことでしたので影響の無いように途中経過を出力してみました。 どちらにしても私の範疇では対処出来そうにないので解決されるまで参考にさせていただきながら見てゆきたいと思います。
yukihisa

2018/08/29 06:35 編集

>30m22,000が最安値なのに >出力結果に一応出てます とのことですが、 >出力結果 >複数で組み合わせる場合 >12m巻 x 3ロール = 24000円 >総計24000円 最安値が24,000になっています。 そのコードを修正するとなると流れ的には、同じロールの間tmpSumとでも名付けて総計とは別にロールの小計を計算しておき、whileをbreakした際にその長さの1ロール分の金額をtmpKinとでもつけて残して、次のforループ中でtmpSum>tmpKinとなったときに総計に足すのをtmpSumからtmpKinに変更してbreakする、といった形になるかと思います。
opyon

2018/08/29 06:41

>事実、5x5の時点で30m22,000が最安値なのに12mx3の24,000が返ってきていますし。 この部分への返信のつもりでしたが言葉足らずですみません。 おっしゃる通り「複数で組み合わせる場合」の「総計」は現状間違っています。 ので修正し後ほど更新つもりです。まだ全てのケースを網羅できていないと思いますが。 あとまだ全体で答えを1つだけ出力するようにはしてません。 途中経過出力したほうが流れが分かるし最安値も見れば分かると思いましたので。 独学での学習と仕事としてやってらっしゃる方達のギャップもとても勉強になります。 私のような者の回答にコメント頂き感謝しています。
opyon

2018/08/29 11:17 編集

作り直してスッキリしました。
opyon

2018/08/29 11:18

「複数で組み合わせる場合」及び小数点対応実装しました。 例題と思われる全4パターン出力可能です。 出力結果はコード内のコメントに書いています。 例題としてとても勉強になりました。 ありがとうございました。
guest

0

[裁断の単位]で30Mを割った商*[裁断の単位]=[30M利用長]
残数を[30M利用長]で割って商がある間は30を使用。(商を30M使用数として加算しておく)
商がなくなった時、余りが12以下なら12、以外は30。
上記でそれぞれの使用数が求められる

追記

余った端生地の金額を差し引かないと最安値は求められないですね。
時間があれば後で見直します。

いや、12M以下だと12Mが安くなるということだけで、切り出せるかどうかでまず判断すれば事足りそう。
やっぱり、12Mと30Mだと金額には差がありますね。

投稿2018/08/29 04:39

編集2018/08/29 06:44
sazi

総合スコア25195

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yukihisa

2018/08/29 04:43 編集

それだとたとえば18mを10枚!としたときに6巻になってしまう気が・・・(本来なら10巻必要)
sazi

2018/08/29 04:58 編集

ああ、そうか。割り切れるようにしたもので割る必要がありますね 修正しました。
yukihisa

2018/08/29 04:54

あとは割引率によって最後は何mまで12を選ぶのかとか、適当に答えたら思ったよりめんどくさかったので後悔しました。。。
sazi

2018/08/29 04:57

金額については、間違っているそうですよ
yukihisa

2018/08/29 04:59

ですね、その点も大きい方*(1-割引率)で閾値割り出す感じに追記しました。
sazi

2018/08/29 05:03

割引率って?質問にあります?
yukihisa

2018/08/29 05:05

ないですが、短い方の単価を100として、大きいほうの単価から割引率を導き出せるので・・・ってそれも書かないとだめか@@;
sazi

2018/08/29 05:07

いやその単価設定が間違えてるんです
yukihisa

2018/08/29 05:09

あぁ、なので単価の数値設定はせずに文字表記にしております。 深く考えると金額部分は全て文字列に⇒全部仮想ならすべて文字列に・・・となりそうではありますが。
sazi

2018/08/29 05:12

それを言い出すと、端生地とかも考えないとって話になるので、12M超えるかどうかの判断でいい気がします。
sazi

2018/08/29 05:15

って?文字出力って何?
yukihisa

2018/08/29 05:20

文字出力?文字表記のことですか? 僕の回答で(30*30mの単価/12mの単価)と文字で表記しています、ということです。
guest

0

回答を考えている時間がなくなってしまいました。ごめんなさい

処理を分解して考えましょう。
算数の問題です。
~~ - 必要な長さを算出 m = a*b~~
~~ - 全体の総延長/30メートル(小数点以下切り捨て) →必要な30mのロール~~
~~ ここで、24m以上、30m以下であれば30mを一枚追加して終わり・・・~~
~~ - その余り/12m →必要な長さ12mのロール~~
~~ - 更にその端数分、12mを一つ追加。~~

投稿2018/08/29 03:01

編集2018/08/29 03:50
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

swordone

2018/08/29 03:32 編集

その計算だと、「5.5mを16枚」というケースでおかしくなる。 5.5*16=88だから、30m3巻で90mとして計算すると16枚取れることになるが、実際には1巻で5枚しか取れないので、1枚足りなくなる。
退会済みユーザー

退会済みユーザー

2018/08/29 03:30

失礼しました。勘違いしておりました。 修正します。
Kazu9999

2018/08/29 03:37

ご回答、ありがとうございます! 全長から算出も考えましたが、全長だとカットされた端数部分も全長の一部になり、 うまくいきませんでした。 例えば、長さ18m、枚数2枚だと、全長が36mになります。 ご提示いただいた計算式だと、 全体の総延長/30メートルだと、30mのロールが1ロール その余り/12m → 12mが2ロール になります。それだと長さ18mは、12m巻では作成することができません。 期待している答えとしては、 30m巻のロールを長さ18mでカットすると、30mを1ロールで、余りが12mあります。 長さが18mでカットのため、12mではたりないため、30mロールをもう1本必要になり、 正解は、30mロール2本が正解です。 端数部を考慮しながら、1ロールあたり作成可能枚数を考慮して、 組み合わせの最適化を行う必要があります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問