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

C++でバイナリ行列内の1から形成される図形の周囲長を求める方法

この問題では、0と1のみで構成される n×m のサイズのバイナリ行列 bin[][] が与えられます。求めるのは、行列内の 1 から形成される図形の周囲長(ペリメーター)です。

周囲長とは、図形を四方すべてから取り囲む外周の長さのことです。

例えば、値が1のセルが1つだけある場合、その周囲長は 4 となります。

C++でバイナリ行列内の1から形成される図形の周囲長を求める方法

入出力例

入力

bin[][] = [1, 0]
          [1, 0]

出力

6

説明

セル (0,0) と (1,0) がつながっており、縦2・横1の長方形を形成しています。したがって、周囲長は 2+2+1+1 = 6 となります。

解法アプローチ

この問題のシンプルな解き方は、行列内のすべての1を見つけ、それぞれが周囲長にどれだけ寄与するかを計算し、その合計を求めるというものです。

行列内の1つの1が周囲長に寄与する度合いは以下の通りです。

  • 最大の寄与は4: その1が上下左右に隣接する1を持たない(孤立している)場合。
  • 最小の寄与は0: その1が上下左右すべてを1に囲まれている場合。

つまり、各セルの周囲長への寄与は「4 − 隣接する1の数」で計算できます。行列の各要素について1かどうかを確認し、1であればその上下左右の隣接セルを調べて寄与を求め、最後にすべてを合計します。

実装例(C++)

#include<iostream>
using namespace std;
#define R 3
#define C 5
int contibutionToPerimeter(int mat[][C], int i, int j) {
    int neighbours = 0;
    if (i > 0 && mat[i - 1][j])
        neighbours++;
    if (j > 0 && mat[i][j - 1])
        neighbours++;
    if (i < R-1 && mat[i + 1][j])
        neighbours++;
    if (j < C-1 && mat[i][j + 1])
        neighbours++;
    return (4 - neighbours);
}
int calcPerimeter(int mat[R][C]){
    int perimeter = 0;
    for (int i = 0; i < R; i++)
        for (int j = 0; j < C; j++)
            if (mat[i][j] == 1)
                perimeter += contibutionToPerimeter(mat, i ,j);
    return perimeter;
}
int main() {
    int mat[R][C] = { {0, 1, 0, 0, 0},
    {1, 1, 1, 1, 0},
    {1, 1, 0, 1, 1} };
    cout<<"1から形成される図形の周囲長は "<<calcPerimeter(mat);
    return 0;
}

出力

1から形成される図形の周囲長は 18

計算量

  • 時間計算量: O(n×m) — 行列の全セルを一度ずつ走査します。
  • 空間計算量: O(1) — 追加の記憶領域は定数分のみ使用します。
  1. C++で三角形の周囲の長さ(外周)を求める方法

    この記事では、三角形の周囲の長さ(外周)とは何か、三角形の種類ごとの周囲の長さの公式、そしてC++でそれらを求めるプログラムの書き方について詳しく解説します。周囲の長さ(Perimeter)とは周囲の長さとは、図形の外側を1周したときの総距離のことです。基本的には、図形を構成するすべての辺の長さを足し合わせたものになります。三角形の周囲の長さ三角形は3つの辺を持つ図形であるため、その周囲の長さは3辺の長さの合計として求められます。公式:周囲の長さ = すべての辺の合計周囲の長さ = x + y + z三角形の周囲の長さを求めるC++プログラムサンプルコード#include <iostre

  2. C++で二分木の葉ノードを繰り返し収集・削除するアルゴリズム

    問題の概要 二分木が与えられているとします。まずすべての葉(子ノードを持たないノード)を収集して取り除き、その操作を木が空になるまで繰り返します。 例えば、次のような二分木が入力として与えられた場合を考えてみます。 このとき、出力は [[4,5,3],[2],[1]] となります。最初のラウンドで葉である 4、5、3 が取り除かれ、続いて 2 が、最後に根の 1 が残るという流れです。 解法のアプローチ この問題は、各ノードの「高さ」(最も深い葉から数えた距離)をDFSで求めると効率的に解けます。同じ高さを持つノードは、必ず同じラウンドで葉になるためです。具体的な手順は以下の通りです。