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

C++でカードを捨てた後の最小合計を求める方法

問題概要

配列Tに5つの数値が格納されているとします。5枚のカードがあり、i番目のカードにはT[i]という数字が書かれています。一部のカードを捨てることができ、目的は残ったカードに書かれた数字の合計を最小化することです。

ただし、同じ数字が書かれた2枚または3枚のカードを捨てる操作は、最大1回までしか行えません。同じ数字のカードを2枚または3枚選べない場合は、カードを捨てません。このとき、実現可能な最小の合計を求める必要があります。

例えば、入力が T = [7, 3, 7, 3, 20] の場合、出力は 26 になります。これは「7」が書かれた2枚のカードを捨てることで、残りの合計が 3 + 3 + 20 = 26 となるためです。

解法のアプローチ

この問題は以下の手順で解くことができます。

  1. 配列Tの全要素の合計mを計算し、同時に各数字の出現回数をサイズ101のカウント配列kに記録します。
  2. 出現回数が2回以上の数字iについて、その数字をmin(3, k[i])枚捨てた場合の合計「m − i × min(3, k[i])」を候補として計算します。
  3. 元の合計mとすべての候補を比較し、最小値Mを返します。
n := 5
m := 0
サイズ101の配列kを定義し、0で初期化
for initialize i := 0, when i < n, update (increase i by 1), do:
    a := T[i]
    m := m + a
    (increase k[a] by 1)
M := m
for initialize i := 0, when i < 101, update (increase i by 1), do:
    if k[i] > 1, then:
        M := minimum of M and (m - i * (minimum of 3 and k[i]))
return M

C++での実装例

理解を深めるために、以下の実装例を見てみましょう。

#include <bits/stdc++.h>
using namespace std;
int solve(vector<int> T)
{
    int n = 5, m = 0, a;
    int k[101] = { 0 };
    for (int i = 0; i < n; i++)
    {
        int a = T[i];
        m += a;
        k[a]++;
    }
    int M = m;
    for (int i = 0; i < 101; i++)
        if (k[i] > 1)
        {
            M = min(M, m - i * (min(3, k[i])));
        }
    return M;
}
int main()
{
    vector<int> T = { 7, 3, 7, 3, 20 };
    cout << solve(T) << endl;
}

入力

{ 7, 3, 7, 3, 20 }

出力

26

まとめ

このアルゴリズムの計算量はO(n)であり、非常に効率的です。ポイントは、同じ数字のカードを捨てることで得られる削減効果を、各数字ごとに一度だけ評価することです。min(3, k[i])を使うことで、2枚または3枚のどちらを捨てた場合により多く合計を減らせるかを自動的に判断しています。

  1. C++でNを約数で繰り返し除算した際の最大合計を求める方法

    問題概要 この問題では、整数 N が与えられます。求めるのは、N を約数で繰り返し除算していったときに得られる値の合計の最大値です。C++ を使ってこの計算を行うプログラムを作成します。 アルゴリズムの考え方 基本的な方針は次のとおりです。 数値 N を 1 になるまで繰り返し除算する。 各ステップで現れる値(元の数と商)をすべて合計する。 合計を最大化するために、毎回最小の約数で割る。 なぜ最小の約数で割るのが最適なのでしょうか。それは、最小の約数で割ると各ステップでの商が最も大きくなり、途中の値が高い水準を保てるためです。結果として、合計も最大になります。 入出力例 入力: N =

  2. C++で解く三角形の最小パス和:動的計画法による効率的なアプローチ

    問題概要 数値が三角形状に配置された構造が与えられます。頂点から最下段まで移動する際、各ステップで「下の行の隣接する数値」にのみ移動できるものとします。このとき、通過する数値の合計が最小となる経路の和を求めてください。 例 入力が以下の場合を考えます。     5   7 3  8 1 2 9 6 4 5 このとき最小の合計は 13 となり、その経路は次のとおりです。 5 + 3 + 1 + 4 アルゴリズム 動的計画法(DP)のメモ化テクニックを利用します。 メモ化用として、1次元配列 memorization を