C++で必要なドリンク詰め替えパックの数を計算する方法
ある週にスタジアムで「a」回の試合と「b」回の記者会見が開催されるとします。スタジアムにはカフェテリアが2つあり、1つは選手用ロッカールーム内に、もう1つは記者会見エリアに設置されています。各カフェテリアにはソフトドリンクディスペンサーがあり、週の初めに補充しておく必要があります。
ロッカールームのディスペンサーは使用頻度が非常に高いため、「c」試合ごとに補充が必要です。一方、会見エリアのディスペンサーは「d」イベントごとに補充が必要です。スタジアム管理委員会は各週の初めに合計「k」個の詰め替えパックを発注でき、ロッカールーム用に「x」個、会見室用に「y」個を割り当てます。ただし、x + y <= k という制約があります。
試合スケジュールが与えられたとき、x と y の値を求めます。必要な詰め替えパックの合計が k を超える場合は「Limit Exceeded」と出力してください。
例えば、入力が a = 8、b = 8、c = 4、d = 6、k = 9 の場合、出力は「2 2」になります。これは、試合8回を4試合ごとの補充で割ると2回、記者会見8回を6イベントごとの補充で割ると切り上げで2回必要となり、合計4個が上限9個以内に収まるためです。
解法のアプローチ
この問題は、切り上げ除算(天井関数)を使うことで簡単に解くことができます。以下の手順に従います。
- ロッカールーム用に必要な補充回数を計算します:a = (c + a - 1) / c(これは a を c で割った切り上げ値と同じ)
- 会見室用に必要な補充回数を計算します:b = (d + b - 1) / d
- a + b <= k であれば、a と b の値を出力します
- それ以外の場合は「Limit Exceeded」を出力します
ポイントは、(c + a - 1) / c という式です。整数除算では小数点以下が切り捨てられるため、分子に (除数 - 1) を加えることで切り上げ除算を実現しています。これにより、端数が発生した場合でも余分な1回分の補充を正しくカウントできます。
実装例
理解を深めるために、以下のC++実装を見てみましょう。
#include <bits/stdc++.h>
using namespace std;
#define N 100
void solve(int a, int b, int c, int d, int k) {
a = (c + a - 1) / c;
b = (d + b - 1) / d;
if(a + b <= k)
cout<<a<<" "<<b<<"\n";
else
cout<<"Limit Exceeded."<<"\n";
}
int main() {
int a = 8, b = 8, c = 4, d = 6, k = 9;
solve(a, b, c, d, k);
return 0;
}
入力
8, 8, 4, 6, 9
出力
2 2
このように、切り上げ除算を活用することで、必要な補充回数を効率的に計算し、発注上限との比較も簡単に行えます。計算量は O(1) と定数時間で済むため、非常に効率的なアルゴリズムです。
-
C++で文字列の部分文字列の総数を求める方法を解説
この記事では、与えられた文字列から作成できる空でない部分文字列の個数を求める方法について解説します。入力 : string = "moon" 出力 : 10 説明 : 部分文字列は m、o、o、n、mo、oo、on、moo、oon、moon の 10 個です。 入力 : string = "yellow" 出力 : 21解法のアプローチ文字列の長さを n とします。上の例からも分かるように、考えられるすべての部分文字列の個数を求めるには、長さ n、(n-1)、(n-2)、(n-3)、……2、1 の部分文字列の個数を順に加算していく必要があります。部分文
-
C++で列車の停車駅の組み合わせ数を求める方法
地点XとYの間にはn個の中間駅があるとします。ここで、「どの2つの停車駅も隣り合わない」という条件のもとで、s個の駅に停車する列車の配置方法が何通りあるかを求める問題を考えてみましょう。この記事では、停車駅の組み合わせ数を求めるためのアプローチを段階的に詳しく解説します。この問題は、本質的には組合せ論の問題であり、s個の停車駅の選び方の総数を求めることになります。 問題を解くアプローチ まず具体例として、中間駅が8個あり、そのうち3個の駅に停車させたい場合を考えてみます。 n = 8, s = 3 このとき、列車が停車できない駅は(n − s)、つまり5個残ることになります。 停車できない