C++で黒く塗られた正方形の中心を見つける方法
n × m のサイズを持つ行列を考えます。各セルは白を表す「W」または黒を表す「B」のいずれかです。この表の中には、奇数の辺の長さを持つ正方形が黒く塗られており、その正方形の中心を見つけることが課題となります。
問題の例
例えば、以下のような入力が与えられたとします。
| W | W | B | B | B | W |
| W | W | B | B | B | W |
| W | W | B | B | B | W |
| W | W | W | W | W | W |
| W | W | W | W | W | W |
この場合、出力は (3, 1) となります。これは、黒い正方形の中心セルが「1行目・3列目」に位置しているためで、結果は(列, 行)の順で出力されます。
解法のアプローチ
この問題は、黒いセル('B')の座標の平均を計算することで解けます。黒く塗られた正方形は上下左右に対称な図形であるため、すべての黒セルの行インデックスの平均と列インデックスの平均は、それぞれ正方形の中心の行・列と一致します。
アルゴリズムの手順
- 行列の行数 n と列数 m を取得する。
- 黒セルの個数 cnt と、座標の累積値 X・Y を 0 で初期化する。
- すべてのセルを走査し、'B' であれば cnt を 1 増やし、X に行番号 i、Y に列番号 j を加算する。
- X を cnt で、Y を cnt で割り、中心座標を求める。
- (Y, X) の順で結果を返す。
計算量は行列の全セルを一度走査するだけなので O(n × m) となり、非常に効率的です。
n := 行列の行数
m := 行列の列数
cnt := 0
X := 0
Y := 0
i を 0 から n 未満まで 1 ずつ増やしながら繰り返す:
j を 0 から m 未満まで 1 ずつ増やしながら繰り返す:
もし matrix[i, j] が 'B' と等しいならば:
cnt を 1 増やす
X := X + i
Y := Y + j
X := X / cnt
Y := Y / cnt
return (Y, X)
C++による実装例
それでは、理解を深めるために実際のコードを見てみましょう。
#include <bits/stdc++.h>
using namespace std;
void solve(vector<vector<char>> matrix){
int n = matrix.size();
int m = matrix[0].size();
int cnt = 0, X = 0, Y = 0;
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++)
if (matrix[i][j] == 'B')
cnt++, X += i, Y += j;
}
X /= cnt;
Y /= cnt;
printf("%d, %d\n", Y, X);
}
int main(){
vector<vector<char>> matrix = { { 'W', 'W', 'B', 'B', 'B', 'W' },
{ 'W', 'W', 'B', 'B', 'B', 'W' }, { 'W', 'W', 'B', 'B', 'B', 'W' },
{ 'W', 'W', 'W', 'W', 'W', 'W' }, { 'W', 'W', 'W', 'W', 'W', 'W' } };
solve(matrix);
}
入力
{ { 'W', 'W', 'B', 'B', 'B', 'W' },
{ 'W', 'W', 'B', 'B', 'B', 'W' }, { 'W', 'W', 'B', 'B', 'B', 'W' },
{ 'W', 'W', 'W', 'W', 'W', 'W' }, { 'W', 'W', 'W', 'W', 'W', 'W' } }
出力
3, 1
-
C++でバッテリーの組み合わせ数を求めるアルゴリズム
最大5回まで使用できるバッテリーがn本あるとします。ここで、3本のバッテリーを必要とするデバイスがあり、デバイスを使用するたびにバッテリーの使用回数が1ずつ増加します。デバイスをk回使用したい場合、それらを動かすために何通りのバッテリーの組み合わせを作れるかを求める必要があります。ただし、1本のバッテリーを複数のデバイスで同時に使用することはできず、すでに5回使用されたバッテリーは組み合わせに含められません。各バッテリーの現在の使用回数は配列battとして与えられます。例えば、入力が n = 6、k = 2、batt = {2, 4, 4, 2, 1, 3} の場合、出力は 1 になります。こ
-
【C++】'D'と'I'の署名から辞書順最小の順列を見つけるアルゴリズム
問題概要D と I の2種類の文字だけで構成された「秘密の署名」を考えます。D は隣接する2つの数の間の減少関係を、I は増加関係を表します。この署名は、1 から n までの相異なる整数をすべて含む特別な整数配列から構成されます。たとえば、署名 DI は [2, 1, 3] や [3, 1, 2] のような配列から構成できます。一方、[3, 2, 4] や [2, 1, 3, 4] のような配列では構成できず、不正な構成となります。ここでの課題は、入力として与えられた署名に一致する [1, 2, ..., n] の順列のうち、辞書順で最小のものを見つけることです。入力が DI の場合、出力は