C++で与えられた行列が「良い行列」かどうかを判定する方法
「良い行列」とは何か
n × n の行列を考えてみましょう。すべての要素のうち 1 以外の数値が、必ず「同じ行に含まれるある数」と「同じ列に含まれるある数」の和として表せるとき、その行列を良い行列(Good Matrix)と呼びます。本記事では、与えられた行列が良い行列かどうかを判定する C++ プログラムを解説します。
たとえば、次のような行列が入力されたとします。
| 1 | 1 | 2 |
| 2 | 3 | 1 |
| 6 | 4 | 1 |
このときの出力は True になります。左下の 6 は、すぐ上の 2 と右隣の 4 の和(2 + 4 = 6)で表せるためです。それ以外の 1 以外の数値も、すべて同じ条件を満たしています。
アルゴリズムの考え方
この問題は、全探索(総当たり)を使えばシンプルに解くことができます。手順は以下の通りです。
- 行列 M のサイズを n とします。
- すべてのセル (i, j) について次の処理を行います。
- 判定用フラグ ok を 0(未発見)で初期化します。
- M[i][j] が 1 でなければ、その値を c として記録します。
- 同じ行 i の各要素 M[i][h] と、同じ列 j の各要素 M[k][j] のすべての組み合わせを調べ、c == M[i][h] + M[k][j] が成立すれば ok を 1 にします。
- 最後まで ok が 0 のまま、かつ M[i][j] が 1 でない場合は、その時点で false を返します。
- すべてのセルが条件を満たしていれば true を返します。
C++ による実装例
理解を深めるために、実際のコードを見てみましょう。
#include <bits/stdc++.h>
using namespace std;
bool solve(vector<vector<int>> M){
int n = M.size();
int c;
bool ok;
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
ok = 0;
if (M[i][j] != 1)
c = M[i][j];
for (int h = 0; h < n; h++){
for (int k = 0; k < n; k++)
if (c == M[i][h] + M[k][j])
ok = 1;
}
if (ok == 0 && M[i][j] != 1){
return false;
}
}
}
return true;
}
int main(){
vector<vector<int>> matrix = { { 1, 1, 2 }, { 2, 3, 1 }, { 6, 4, 1 } };
cout << solve(matrix) << endl;
}
入力
{ { 1, 1, 2 }, { 2, 3, 1 }, { 6, 4, 1 } }
出力
1
計算量について
このアルゴリズムは 4 重のループを使用するため、時間計算量は O(n⁴) となります。一方で、追加のメモリは定数個の変数のみなので、空間計算量は O(1) です。小〜中規模の行列であれば十分実用的ですが、より大きな行列を扱う場合は、あらかじめ各行・各列の値の集合を構築しておくことで O(n³) まで高速化できるなど、効率的な手法を検討するとよいでしょう。
-
C++で木グラフ(ツリーグラフ)が線形かどうかを判定する方法
本記事では、C++を使って与えられた木グラフ(ツリーグラフ)が「線形(リニア)」であるかどうかを判定する方法を解説します。線形の木グラフとは、すべてのノード(頂点)を一本の線上に連ねて表現できるグラフのことです。 線形木グラフとは たとえば、下の図のようなグラフは一本の線で表現できるため、線形の木グラフです。 一方、次のように途中で分岐(複数の子ノード)を持つ木は線形ではありません。 線形グラフを判定する条件 ある木グラフが線形かどうかは、次の2つの条件で確認できます。 ノード数が1の場合、その木グラフは線形である。 n個のノードのうち (n − 2) 個のノードの次数が2である場合、そ
-
与えられた二分木がAVL木かどうかを判定するC++プログラム
AVL木(AVL Tree)とは、すべてのノードにおいて、左部分木と右部分木の高さの差が1を超えないことが保証されている自己平衡型二分探索木です。このバランス特性により、木が片側に偏ることを防ぎ、検索・挿入・削除などの操作を常に高い効率で実行できます。 この記事では、与えられた二分木がAVL木であるかどうかを判定するC++プログラムを紹介します。 AVL木の条件 ある二分木がAVL木であるためには、次の条件を満たす必要があります。 すべてのノードで「左部分木の高さ − 右部分木の高さ」の絶対値が1以下である さらに、左右の部分木もそれぞれAVL木である(条件は再帰的に適用される) アルゴ