6

これは、アルゴリズムの最終試験の問題でした。教授が試験のコピーを家に持ち帰らせてくれたので、そのままです。

  1. (20 点) I = {r1,r2,...,rn} をn 個の任意の正の整数の集合とし、Iの値を区別します。 は任意のソートされた順序で与えられていません。I 'のすべての要素の総和が正確に 100*ceil(n^.5) になるような I のサブセット I' を見つけたいとします ( I の各要素はI 'に最大1現れることができます)。この問題を解決するための O( n ) 時間アルゴリズムを提示します。

私が知る限り、それは基本的にナップザック問題の特別なケースであり、サブセット和問題としても知られています...どちらもNPにあり、理論的には線形時間で解決することは不可能ですか?

それで...これはひっかけ問題でしたか?


この SO 投稿では、基本的に、重みが制限されている場合は疑似多項式 (線形) 時間近似を行うことができると説明していますが、試験問題では重みが制限されておらず、どちらにしても試験の全体的な難しさを考えるとショックを受けるでしょう教授が、あいまいな動的最適化アルゴリズムを知っている/考え出すことを期待していた場合。

4

3 に答える 3

4

この問題を可能にする 2 つの要因があります。

  1. 入力はサイズ O(sqrt(n)) に切り詰めることができます。負の入力がないため、100*sqrt(n) より大きい数値は破棄できます。また、すべての入力が異なるため、重要な入力は最大で 100*sqrt(n) であることがわかります。
  2. 競技場のサイズは O(sqrt(n)) です。重要な O(sqrt(n)) 入力を結合する O(2^sqrt(n)) 通りの方法がありますが、100*sqrt(n) の範囲を逸脱したり、重複してヒットしたりする組み合わせを気にする必要はありません。すでに到達できる目標。

基本的に、この問題は、「到達数」空間の各部分に対して各入力が何らかの形でチェックされる動的計画法を叫びます。

解決策は、(正しい方向にスキャンすることによって) 数値がそれ自体から離れないようにすること、各数値を 1 回だけ見ること、および後で解決策を再構築するのに十分な情報を自分自身に提供することの問題になります。

所定の時間内に問題を解決する C# コードを次に示します。

int[] FindSubsetToImpliedTarget(int[] inputs) {
    var target = 100*(int)Math.Ceiling(Math.Sqrt(inputs.Count));

    // build up how-X-was-reached table
    var reached = new int?[target+1];
    reached[0] = 0; // the empty set reaches 0
    foreach (var e in inputs) {
        // we go backwards to avoid reaching off of ourselves
        for (var i = target; i >= e; i--) {
            if (reached[i-e].HasValue) {
                reached[i] = e;
            }
        }
    }

    // was target even reached?
    if (!reached[target].HasValue) return null;

    // build result by back-tracking via the logged reached values
    var result = new List<int>();
    for (var i = target; reached[i] != 0; i -= reached[i].Value) {
        result.Add(reached[i].Value);
    }
    return result.ToArray();
}

上記のコードを実際にテストしたわけではないので、タイプミスやオフバイワンに注意してください。

于 2013-12-17T08:32:18.687 に答える
2

部分和問題の典型的な DP アルゴリズムでは、O(N)時間のかかるアルゴリズムが得られます。(boolean)を使用dp[i][k]して、最初の i 個のアイテムが合計 k のサブセットを持っているかどうかを示します。遷移方程式は次のとおりです。

dp[i][k] = (dp[i-1][k-v[i] || dp[i-1][k]),

ここでO(NM)、N はセットのサイズ、M は目標とする合計です。要素は個別であり、合計は に等しくなければならないため100*ceil(n^.5)、最大で最初の 100*ceil(n^.5) 項目を考慮するだけで、 と が得られN<=100*ceil(n^.5)ますM = 100*ceil(n^.5)

DPアルゴリズムはO(N*M) = O(100*ceil(n^.5) * 100*ceil(n^.5)) = O(n).

于 2013-12-17T09:10:04.420 に答える
1

以下は、O(n)時間の簡単なソリューションです。

必要な合計Sは のオーダーであるためO(n^0.5)、複雑なアルゴリズムを定式化する場合、アルゴリズムS^2は有効な複雑さになるため、問題ありませんO(n)

  1. すべての要素を 1 回繰り返し、値が S より小さいかどうかを確認します。そうであれば、それを新しい配列にプッシュします。この配列には、最大で S 個の要素 (O(n^.5)) が含まれます。

  2. この配列を O(sqrt(n)*logn) 時間 ( < O(n)) で降順に並べ替えます。これは、すべての自然数に対して logn <= sqrt(n) であるためです。https://math.stackexchange.com/questions/65793/how-to-prove-log-n-leq-sqrt-n-over-natural-numbers

この問題は、W = S、要素数 = S (上限) の 1D ナップザック問題です。

アイテムの総重量を最大化し、それが S に等しいかどうかを確認します。

これは、線形時間で動的計画法を使用して解決できます (WRT W ~ S に対する線形)。

于 2013-12-17T07:41:53.117 に答える