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

C++で1人目の学生に割り当て可能な最大スコアを求める方法

n 個の要素を持つ配列 A と数値 m が与えられているとします。n 人の学生が試験を受けており、取りうる最高得点は m です。A[i] は i 番目の学生の得点を表します。各学生の得点は自由に変更できますが、次の条件を満たす必要があります。

  • どの得点も m を超えないこと
  • すべての得点が整数であること
  • 全学生の平均点が変化しないこと

このとき、1 人目の学生の得点を最大化したい場合、割り当てられる最高得点はいくつになるでしょうか。

たとえば、入力が A = [1, 2, 3, 4]、m = 10 の場合を考えてみましょう。このときの出力は 10 になります。元の平均点は 2.5 ですが、得点を [10, 0, 0, 0] と設定しても合計点(したがって平均点)は変わらず、1 人目の得点を最大にできます。

解法のアプローチ

この問題の鍵となるのは「平均点が変わらない」という条件です。学生の人数は固定なので、平均点が変わらないということは、合計点も変わらないことを意味します。したがって、1 人目の学生に割り当てられる最大の得点は、次の 2 つの制約から決まります。

  • 得点は m を超えられない
  • 他の学生の得点は 0 以上であるため、1 人目の得点は全体の合計点(sum)を超えられない

よって、答えは m と sum のうち小さい方(min(m, sum))となります。

手順

  1. 合計 sum を 0 で初期化する
  2. n を配列 A のサイズとする
  3. j = 0 から n-1 までループし、sum に A[j] を順に加算する
  4. m と sum の最小値を返す

C++ 実装例

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

#include <bits/stdc++.h>
using namespace std;
int solve(vector<int> A, int m){
    int sum = 0;
    int n = A.size();
    for (int j = 0; j < n; j++){
        sum += A[j];
    }
    return min(m, sum);
}
int main(){
    vector<int> A = { 1, 2, 3, 4 };
    int m = 10;
    cout << solve(A, m) << endl;
}

入力

{ 1, 2, 3, 4 }, 10

出力

10
  1. 【C++】グラフの連結性を保ちながら辺を削除し、スコアの最大削減量を求める方法

    問題概要 n 個の頂点と m 本の辺からなる重み付き無向グラフを考えます。グラフの「スコア」は、含まれるすべての辺の重みの総和として定義されます。辺の重みは負になることもあり、そのような辺を取り除くとかえってスコアが増えてしまいます。 ここで求めたいのは、グラフを連結状態に保ったまま不要な辺を削除してスコアを最小化し、「スコアを最大でどれだけ減らせるか」を計算することです。 グラフは配列 edges として与えられ、各要素は {weight, {vertex1, vertex2}}(重みと両端の頂点)という形式で表されます。 入力例と出力 たとえば n = 5、m = 6、edges = {

  2. C++で数Nをk個の数の積として表現できるかどうかを判定する方法

    数Nと整数kが与えられたとき、Nをk個の数(1より大きい数)の積として表現できるかどうかを判定する方法を解説します。例えば、N=54、k=3が与えられた場合、54 = 2 × 3 × 9 と分解できるため「2, 3, 9」のように出力します。表現できない場合は、その旨を出力します。アルゴリズムの考え方この問題を解くには、まずNのすべての素因数を求め、それらをvectorに格納します。1より大きいk個の数を得るには、vectorのサイズがk以上であるかを確認します。サイズがk未満の場合は「-1」を返して表現不可を示します。サイズがk以上であれば、最初のk-1個の因数をそのまま出力し、最後の数は残