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

C++で指定された制約を満たす行列内の最長パスを検索する方法

n次の正方行列を考えます。この行列にはすべて異なる要素が含まれています。ここで、パス上のすべてのセルが差1で増加順に並ぶような最長パスを求める必要があります。あるセルからは、左・右・上・下の4方向に移動できます。例えば、次のような行列があるとします。

129
538
467

この場合の出力は 4 になります。最長パスは 6→7→8→9 となるためです。

解法のアプローチ

この問題を解くためには、次の考え方に従います。まず、すべてのセルから始まる最長パスを計算します。すべてのセルについて最長パスが求まったら、その中の最大値を返します。

このアプローチで重要なポイントは、多くの重複する部分問題が存在することです。したがって、この問題は動的計画法(Dynamic Programming)を用いて効率的に解くことができます。ここでは、ルックアップテーブル dp[][] を使用して、ある問題がすでに解決済みかどうかを確認します。

実装例

#include <iostream>
#define n 3
using namespace std;
int getLongestPathLengthUtil(int i, int j, int matrix[n][n], int table[n][n]) {
    if (i < 0 || i >= n || j < 0 || j >= n)
    return 0;
    if (table[i][j] != -1)
        return table[i][j];
    int x = INT_MIN, y = INT_MIN, z = INT_MIN, w = INT_MIN;
    if (j < n - 1 && ((matrix[i][j] + 1) == matrix[i][j + 1]))
        x = 1 + getLongestPathLengthUtil(i, j + 1, matrix, table);
    if (j > 0 && (matrix[i][j] + 1 == matrix[i][j - 1]))
        y = 1 + getLongestPathLengthUtil(i, j - 1, matrix, table);
    if (i > 0 && (matrix[i][j] + 1 == matrix[i - 1][j]))
        z = 1 + getLongestPathLengthUtil(i - 1, j, matrix, table);
    if (i < n - 1 && (matrix[i][j] + 1 == matrix[i + 1][j]))
        w = 1 + getLongestPathLengthUtil(i + 1, j, matrix, table);
        return table[i][j] = max(x, max(y, max(z, max(w, 1))));
}
int getLongestPathLength(int matrix[n][n]) {
    int result = 1;
    int table[n][n];
    for(int i = 0; i < n; i++)
    for(int j = 0; j < n; j++)
    table[i][j] = -1;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (table[i][j] == -1)
            getLongestPathLengthUtil(i, j, matrix, table);
            result = max(result, table[i][j]);
        }
    }
    return result;
}
int main() {
    int mat[n][n] = { { 1, 2, 9 },
    { 5, 3, 8 },
    { 4, 6, 7 } };
    cout << "Length of the longest path is "<< getLongestPathLength(mat);
}

実行結果

Length of the longest path is 4

計算量について

メモ化により各セルの結果は一度だけ計算されるため、このアルゴリズムの時間計算量は O(n²) となり、行列のサイズが大きくなっても効率的に動作します。


  1. C++で指定した開始文字から最長の連続パスの長さを求める方法

    異なる文字が格納された行列(マトリックス)が与えられます。ある文字を起点として、現在の文字より1つ大きい連続した文字(例:a→b→c→d)をたどりながら、最長のパスの長さを見つけることが課題です。移動は、縦・横・斜めを含む8方向の隣接セルに対して可能です。 例えば、下図のような行列が与えられ、開始文字を「E」とします。 この行列で開始文字「e」から探索すると、最長の連続パスの長さは5となります。 アルゴリズムの考え方 最長パスを見つけるには、深さ優先探索(DFS)アルゴリズムを使用します。DFSの実行中には、同じ部分問題が何度も発生することがあります。このような部分問題を繰り返し計算しないよ

  2. C++で最長増加部分列(LIS)を求めるプログラムの解説と実装例

    最長増加部分列(Longest Increasing Subsequence:LIS)とは、数列の中から一部の要素を取り出して作った部分列のうち、各要素が直前の要素よりも常に大きくなるような列のことです。本記事では、整数の集合が与えられたときに、その最長増加部分列の長さを動的計画法(DP)を用いて求める方法を解説します。問題の例入力:整数の集合 {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15} 出力:最長増加部分列の長さ → 6 該当する部分列は 0, 2, 6, 9, 13, 15アルゴリズムの考え方この問題は動的計画法を使って効率