最安値を達成するには《DP・漸化式》

DPメニュー【最安値を達成するには 1 〜 4】

【最安値を達成するには 1】コード

reader.on('close', () => {
   const [n, a, b] = lines[0].split(' ').map(Number);
   const dp = [0, a];  // 0 個の価格は 0 円, 1個の値段は a
   for (let i = 2; i <= n; i++) {  // ループの範囲は 2 個 ~ n
      dp[i] = Math.min(dp[i - 1] + a, dp[i - 2] + b);  //dp[i]は dp[i - 1] + a 円 と dp[i - 2] + b 円 の安い方
   }
   console.log(dp[n]);
});
hogeちゃんの画像

dp[i]i の値は 購入するリンゴの個数 で i 個のリンゴの価格は i – 1 個の価格 + a 円と i – 2 個の価格 + b 円 を比較して 安い方でした。

【最安値を達成するには 2】コード 1/2

reader.on('close', () => {
   const [n, a, b] = lines[0].split(' ').map(Number);
   const dp = [0, a];  // 0 個の価格は 0 円, 1個の値段は a
   for (let i = 2; i <= n; i++) {  // ループの範囲は 2 個 ~ n
      if (i >= 5) {  // 5 個以上なら…
         dp[i] = Math.min(dp[i - 2] + a, dp[i - 5] + b);  // dp[i]は dp[i - 1] + a 円 と dp[i - 5] + b 円 の安い方
      } else if (i >= 2) {  //  5 個未満, 2 個以上なら…
         dp[i] = Math.min(dp[i - 2] + a, b);  // dp[i]は dp[i - 1] + a 円 と b 円 の安い方
      }
   }
   console.log(dp[n]);
// console.log(dp);
});
hogeちゃんの画像

解説の解き方と違っていますが こんな感じになりました。

【最安値を達成するには 2】コード 2/2

reader.on('close', () => {
   const [n, a, b] = lines[0].split(' ').map(Number);
   const dp = new Array(n + 5).fill(10000000);
   dp[0] = 0;
   for (let i = 1; i < n + 5; i++) {
      if (i >= 2) {
         dp[i] = Math.min(dp[i], dp[i - 2] + a);
      }
      if (i >= 5) {
         dp[i] = Math.min(dp[i], dp[i - 5] + b);
      }
   }
// console.log(dp);
   console.log(Math.min(...dp.slice(n)));  // 解答①
   const dp2 = [];
   for (let i = n + 4; i >= 0; i--) {
      dp2[i] = dp[i];
      for (let j = i + 1; j < n + 5; j++) {
         dp2[i] = Math.min(dp2[i], dp[j]);
      }
   }
// console.log(dp2);
   console.log(dp2[n]);  // 解答②
   for (let i = n + 3; i >= 1; i--) {
      dp[i] = Math.min(dp[i], dp[i + 1]);
   }
// console.log(dp);
   console.log(dp[n]);  // 解答③
});
hogeちゃんの画像

解答コード例・解説を参照しました。解き方が3通り(解答①〜③)ありますが 出力値は全て同じでした。

【最安値を達成するには 3】コード 1/2

reader.on('close', () => {
   const [n, x, a, y, b] = lines[0].split(' ').map(Number);
   const dp = [0, a];  // 0 個の価格は 0 円, 1個の値段は a
   for (let i = 2; i <= n; i++) {  // ループの範囲は 2 個 ~ n
      if (i >= y) {  // y 個以上なら…
         dp[i] = Math.min(dp[i - x] + a, dp[i - y] + b);  // dp[i]は dp[i - x] + a 円 と dp[i - y] + b 円 の安い方
      } else if (i >= x) {  // y 個未満, x 個以上なら…
         dp[i] = Math.min(dp[i - x] + a, b);  // dp[i]は dp[i - 1] + a 円 と  b 円 の安い方
      }else {  // x 個未満なら…
          dp[i] = a;  // dp[i] は a
      }
   }
   console.log(dp[n]);
// console.log(dp);
});
hogeちゃんの画像

【STEP: 2】コード 1/2 とほぼ同じです。2 個が a 円で 5 個が bだったのが x 個が a 円で y 個が b になったので 2 → x, 5 → y になりました。

【最安値を達成するには 3】コード 2/2

reader.on('close', () => {
   const [n, x, a, y, b] = lines[0].split(' ').map(Number);
   const dp = new Array(n + y).fill(10000000);
   dp[0] = 0;
   for (let i = 1; i < n + y; i++) {
      if (i >= 2) {
         dp[i] = Math.min(dp[i], dp[i - 2] + a);
      }
      if (i >= y) {
         dp[i] = Math.min(dp[i], dp[i - y] + b);
      }
   }
// console.log(dp);
   console.log(Math.min(...dp.slice(n)));  // 解答①
   const dp2 = [];
   for (let i = n + y - 1; i >= 0; i--) {
      dp2[i] = dp[i];
      for (let j = i + 1; j < n + y; j++) {
         dp2[i] = Math.min(dp2[i], dp[j]);
      }
   }
// console.log(dp2);
   console.log(dp2[n]);  // 解答②
   for (let i = n + y - 2; i >= 1; i--) {
      dp[i] = Math.min(dp[i], dp[i + 1]);
   }
// console.log(dp);
   console.log(dp[n]);  // 解答③
});
hogeちゃんの画像

解答コード例・解説を参照しました。

【最安値を達成するには 4】コード 1/2

reader.on('close', () => {
   const [n, x, a, y, b, z, c] = lines[0].split(' ').map(Number);
   const dp = [0, a];  // 0 個の価格は 0 円, 1個の値段は a
   for (let i = 2; i <= n; i++) {  // ループの範囲は 2 個 ~ n
      if (i >= z) {  // z 個以上なら…
         dp[i] = Math.min(dp[i - x] + a, dp[i - y] + b, dp[i - z] + c);  // dp[i]は dp[i - x] + a 円 と dp[i - y] + b 円 と dp[i - z] + c 円の最安
      } else if (i >= y) {  // z 個未満, y 個以上なら…
         dp[i] = Math.min(dp[i - x] + a, dp[i - y] + b, c);  // dp[i]は dp[i - x] + a 円 と dp[i - y] + bdp[i - z] + c 円の最安
      } else if (i >= x) {  // y 個未満, x 個以上なら…
         dp[i] = Math.min(dp[i - x] + a, b);  // dp[i]は dp[i - x] + a 円 と b 円 の最安
      } else {  // x 個未満なら…
         dp[i] = a;  // dp[i] は a
      }
   }
   console.log(dp[n]);
// console.log(dp);
});
hogeちゃんの画像

x 個が a・y 個が b・z 個が cと 購入方法が 3パターンになりました。

【最安値を達成するには 4】コード 2/2

reader.on('close', () => {
   const [n, x, a, y, b, z, c] = lines[0].split(' ').map(Number);
   const dp = new Array(n + z).fill(10000000);
   dp[0] = 0;
   for (let i = 1; i < n + z; i++) {
      if (i >= x) {
         dp[i] = Math.min(dp[i], dp[i - x] + a);
      }
      if (i >= y) {
         dp[i] = Math.min(dp[i], dp[i - y] + b);
      }
     if (i >= z) {  // z 個以上なら…
         dp[i] = Math.min(dp[i], dp[i - z] + c);
      }
   }
// console.log(dp);
   console.log(Math.min(...dp.slice(n)));  // 解答①
   const dp2 = [];
   for (let i = n + z - 1; i >= 0; i--) {
      dp2[i] = dp[i];
      for (let j = i + 1; j < n + z; j++) {
         dp2[i] = Math.min(dp2[i], dp[j]);
      }
   }
// console.log(dp2);
   console.log(dp2[n]);  // 解答②
   for (let i = n + z - 2; i >= 1; i--) {
      dp[i] = Math.min(dp[i], dp[i + 1]);
   }
// console.log(dp);
   console.log(dp[n]);  // 解答③
});
hogeちゃんの画像

解答コード例・解説を参照しました。

 

コメント