C++
 Computer >> コンピューター >  >> プログラミング >> C++

【C++】ちょうどnリットルの水を購入するための最小金額を求めるプログラム

3つの整数 nab が与えられたとします。私たちは n リットルの水をちょうど購入したいと考えています。

近くの店で売られているのは、次の2種類の水のボトルだけです。

  • 1リットル入りボトル:価格 a ルピー
  • 2リットル入りボトル:価格 b ルピー

できるだけお金をかけずに済ませたいので、ちょうど n リットルの水を購入するために必要な最小金額を求めます。

入力例と出力例

たとえば、入力が n = 7a = 3b = 2 の場合、出力は 9 になります。

その理由は以下の通りです。

  • 2リットルボトルを3本購入 → 6リットル分を6ルピーで確保
  • 残り1リットルは1リットルボトルを1本購入 → 3ルピー

合計金額は 6 + 3 = 9 ルピーとなり、これが最小の支払額です。

解法のアプローチ

この問題は貪欲法(グリーディ法)でシンプルに解くことができます。ポイントは次の通りです。

  1. まず、「2リットルボトル1本の価格 b」と「1リットルボトル2本の価格 a × 2」を比較し、安い方を2リットルあたりの実効価格として採用します。これにより、1リットルボトル2本の方が安いケースにも対応できます。
  2. n を2で割った商の分だけ2リットルボトルを購入し、n が奇数の場合は余りの1リットルを1リットルボトルで補います。

アルゴリズムの手順

b := min(a * 2, b)
return (n / 2 * b) + (n mod 2) * a

C++での実装例

以下に、実際のC++コードを示します。

#include <bits/stdc++.h>
using namespace std;

int solve(int n, int a, int b) {
    // 2リットル分のコストは、2リットルボトル1本か1リットルボトル2本の安い方
    b = min(a * 2, b);
    // 2リットルボトルで n/2 本分を買い、奇数なら残り1リットルを1リットルボトルで補う
    return n / 2 * b + n % 2 * a;
}

int main() {
    int n = 7;
    int a = 3;
    int b = 2;
    cout << solve(n, a, b) << endl;
}

入力

7, 3, 2

出力

9

計算量について

このアルゴリズムは比較と四則演算を定数回行うだけでよいため、時間計算量 O(1)空間計算量 O(1) で動作します。n がどれほど大きくなっても高速に答えを求められるのが特徴です。

  1. C++で2次元デカルト座標点をすべて接続する最小コストを求めるプログラム

    問題の概要2次元デカルト座標上の点のリスト(x, y)が与えられたとします。点(x0, y0)と(x1, y1)を接続するときのコストは、|x0 − x1| + |y0 − y1|(マンハッタン距離)で表されます。任意の数の点を接続できる場合、すべての点がひとつのパスでつながるようにするために必要な最小コストを求めます。例えば、入力が points = [[0, 0], [0, 2], [0, -2], [2, 0], [-2, 0], [2, 3], [2, -3]] の場合を考えてみましょう。このとき出力は 14 になります。その理由は以下の通りです。(0, 0) から (0, 2)、(0

  2. C++でノード値の合計が最小となる二分木のレベルを求めるプログラム

    二分木(バイナリツリー)を考えます。根(ルート)のレベルを1とし、その子のレベルを2、さらにその下のレベルを3というように定義します。このとき、レベルXに存在するすべてのノードの値の合計が最小になるような、最も小さいレベルXを見つけるのが本記事の目的です。例として、次のような二分木を考えてみましょう。この場合、出力は 2 となります。なぜなら、レベル2のノードの値の合計は 4 + (-10) = -6 となり、これが全レベルの中で最小だからです。解法のアプローチこの問題は、幅優先探索(BFS)を使って各レベルごとにノードの値の合計を計算し、その中で最小となるレベルを記録していくことで解けます。