C++でn×nの正方形ボード上の勝利マスを数える方法
n×n の正方形ボードがあり、Amal(アマル)と Bimal(ビマル)がゲームを行っています。二人はゲーム中、独自のルールに従ってボードの各マスに数字を書き込んでいきます。現在見えているのはゲーム終了後の盤面です。どちらが勝者かを判定するには、「勝利マス」の数を数える必要があります。
あるマスが勝利マスであるかは、次のように判定します。
- そのマスと同じ列にあるすべての数字の合計を求めます。
- 同じ行にあるすべての数字の合計を別途求めます。
- 列の合計が行の合計より厳密に大きい場合、そのマスは勝利マスとなります。
たとえば、次のような入力が与えられたとします。
| 5 | 7 | 8 | 4 |
| 9 | 5 | 3 | 2 |
| 1 | 6 | 6 | 4 |
| 9 | 5 | 7 | 3 |
このときの出力は 6 になります。勝利マスに該当するのは、下の表でオレンジ色で示した6つのマスです。
| 5 | 7 | 8 | 4 |
| 9 | 5 | 3 | 2 |
| 1 | 6 | 6 | 4 |
| 9 | 5 | 7 | 3 |
アルゴリズムの手順
この問題は次の手順で解くことができます。
- 勝利マスを数える変数 t を 0 で初期化します。
- 盤面上のすべてのマス (i, j) を走査し、行 i の合計 s と列 j の合計 l をそれぞれ計算します。
- l > s が成り立てば t を 1 増やします。
- すべてのマスを調べ終えたら、t を結果として返します。
C++による実装例
理解を深めるために、実際の実装を見てみましょう。
#include <bits/stdc++.h>
using namespace std;
int solve(vector<vector<int>> M){
int t = 0;
int n = M.size();
for (int i = 0; i <= n - 1; i++)
for (int j = 0; j <= n - 1; j++){
int s = 0;
int l = 0;
for (int k = 0; k <= n - 1; k++){
s += M[i][k];
l += M[k][j];
}
if (l > s)
t++;
}
return t;
}
int main(){
vector<vector<int>> matrix = { { 5, 7, 8, 4 }, { 9, 5, 3, 2 }, { 1, 6, 6, 4 }, { 9, 5, 7, 3 } };
cout << solve(matrix) << endl;
}
この実装では、全マスについて行と列の合計をそれぞれ計算するため、時間計算量は O(n³) になります。n が小さければ十分実用的ですが、盤面が大きくなる場合は、あらかじめ各行・各列の合計をまとめて計算しておくことで O(n²) まで高速化できます。
入力
{ { 5, 7, 8, 4 }, { 9, 5, 3, 2 }, { 1, 6, 6, 4 }, { 9, 5, 7, 3 } }出力
6
-
C++でN番目の非平方数を求める方法を解説
2、3、5、7、8のように、ある整数の2乗にはならない数(非平方数)は身近にたくさん存在します。しかし非平方数は無限にあるため、そのすべてを把握することはできません。この記事では、非平方数とは何かを丁寧に解説し、C++でN番目の非平方数を求める具体的な方法を紹介します。 N番目の非平方数とは ある数が別の整数の2乗で表せるとき、その数は完全平方数と呼ばれます。完全平方数の例は以下の通りです。 1 は 1 の2乗 4 は 2 の2乗 9 は 3 の2乗 16 は 4 の2乗 25 は 5 の2乗 一方、どの整数の2乗にもならない数を非平方数と呼びます。最初の15個の非平方数は次のようになります
-
C++で行列内の正方形の最大辺の長さを求めるアルゴリズム
この問題では、サイズ n × n の2次元行列 mat[][] が与えられます(n は奇数)。求めるのは、行列と同じ中心を持ち、外周の値がすべて等しい正方形の最大の辺の長さです。問題の概要与えられた行列の中から、行列の中心を共有する正方形の部分行列を探し、その外周(周囲)を構成する要素がすべて同じ値である場合に、その正方形の辺の長さを返します。条件を満たす複数の正方形がある場合は、最も大きいものを選びます。入力例mat[][] = { {2, 4, 6, 6, 5}, {1, 7, 7, 7, 3}, {5, 7, 0, 7, 1}, {3, 7, 7, 7,