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

水注ぎゲームで全員が勝者になるかを判定するC++コード

n個の要素を持つ配列Aと、数値sが与えられます。テーブルの上には、空のコップが1つと、水の入ったコップがn個置かれています。このゲームには複数のプレイヤーが参加し、各ターンでプレイヤーは水の入ったコップを1つ選び、その水をすべて空のコップに注ぎます。コップがあふれてしまった場合、そのプレイヤーは負けとなります。ここで、すべてのプレイヤーが勝者になれるかどうか(コップがあふれないかどうか)を判定する必要があります。なお、コップがすでに満杯になっている場合、次のプレイヤーは自分のターンを行いません。sは空のコップの容量を、A[i]はi番目のコップに入っている水の量を表します。

例えば、入力がA = [3, 1, 3]、s = 4である場合、出力はTrueになります。1番目と2番目のプレイヤーが水を注ぐとコップがちょうど満杯になり、最後のプレイヤーはターンを行わないためです。

解法の手順

この問題を解くには、以下の手順に従います。

k := 0
n := Aのサイズ
配列Aをソートする
i := 0 で初期化し、i < n - 1 の間、i を 1 ずつ増やしながら以下を繰り返す:
    k := k + A[i]
k > s の場合:
    false を返す
それ以外の場合:
    true を返す

アプローチのポイント

配列をソートした後、最も水量の多いコップを除いた残りのn-1個のコップに入っている水の合計を求めます。この合計が容量s以下であれば、途中でコップがあふれることなく水を注ぐことができ、全員が勝者となります。計算量は、ソートにO(n log n)、合計の計算にO(n)と非常に効率的です。

実装例

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

#include <bits/stdc++.h>
using namespace std;
bool solve(vector<int> A, int s){
    int k = 0;
    int n = A.size();
    sort(A.begin(), A.end());
    for (int i = 0; i < n - 1; i++)
        k += A[i];
    if (k > s)
        return false;
    else
        return true;
}
int main(){
    vector<int> A = { 3, 1, 3 };
    int s = 4;
    cout << solve(A, s) << endl;
}

入力

{ 3, 1, 3 }, 4

出力

1

  1. C++で二分木が同型(アイソモーフィック)かどうかを判定する方法

    二分木では、各ノードが「左の子」と「右の子」という2つの子ノードを持ちます。ここでは、2つの二分木が与えられたとき、一方の木を左右反転(フリップ)することでもう一方の木が得られるかどうかを判定する問題を解説します。一方の木を反転することでもう一方の木と同じ構造が得られる場合、その2つの木は「同型(アイソモーフィック)」であると定義されます。具体例入力1出力Isomorphic(同型)説明:Tree-2はTree-1を左右反転することで得られるため、この2つの木は同型です。解き方のアプローチこの問題は再帰的なアプローチで効率的に解くことができます。ブール型の関数を用意し、両方の木のルートノードを

  2. 【C++入門】バイナリ文字列の「1」の間に「0」が含まれているかを判定する方法

    今回は少し面白い文字列処理の問題を取り上げます。与えられたバイナリ文字列(0と1のみで構成された文字列)について、「1」の並びの中に「0」が挟まっていないかどうかを判定します。「0」が含まれていなければその文字列は有効(valid)、含まれていれば無効(invalid)とみなします。問題の例次の3つの文字列を見てみましょう。A:10001111010B:00001111100C:01111101111この中で有効なのは B の「00001111100」だけです。B は先頭から最初の「1」まで、そして最後の「1」以降には「0」がありますが、連続する「1」のブロック内部には「0」が一切存在しないた