Javaにおける動的計画法を用いた部分和問題のアルゴリズム


まず、部分和問題のアルゴリズムには2つのアプローチがあります。1つは再帰的なトップダウンの方法であり、もう1つは反復的なボトムアップの方法です。ここでは、反復的なボトムアップの方法を紹介します。

  1. ボトムアップのアルゴリズムの実装:
    • 部分和問題を解くために必要な配列を作成します。この配列は、[要素の数 + 1][目標の合計値 + 1]のサイズを持ちます。
    • 配列の要素をすべて初期化し、部分和問題の基本的な状態を設定します。つまり、配列の最初の行と最初の列を0で埋めます。
    • 配列の2行目から順に、与えられた整数の集合の要素を1つずつ取り出します。
    • 配列の各要素に対して、以下の条件分岐を行います。
      • もし現在の要素を選んで目標の合計値を達成できる場合、配列の対応する位置を1に更新します。
      • もし現在の要素を選ばずに目標の合計値を達成できる場合、配列の対応する位置を0または1に更新します(状況によって異なります)。
    • 配列の最後の要素が1であれば、目標の合計値を達成する組み合わせが存在します。そうでなければ、存在しません。

以下に、Javaで部分和問題のアルゴリズムを実装する例を示します。

public class SubsetSum {
    public static boolean hasSubsetSum(int[] set, int target) {
        int n = set.length;
        boolean[][] dp = new boolean[n + 1][target + 1];

        // ベースケースの初期化
        for (int i = 0; i <= n; i++) {
            dp[i][0] = true;
        }
// ボトムアップの計算
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= target; j++) {
                if (set[i - 1] <= j) {
                    dp[i][j] = dp[i - 1][j - set[i - 1]] || dp[i - 1][j];
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }

        return dp[n][target];
    }

    public static void main(String[] args) {
        int[] set = {3, 34, 4, 12, 5, 2};
        int target = 9;

        if (hasSubsetSum(set, target)) {
            System.out.println("目標の合計値を達成する組み合わせが存在します。");
        } else {
            System.out.println("目標の合計値を達成できる組み合わせは存在しません。");
        }
    }
}