すべての答えを得るために高速動的計画法アルゴリズムを実行する

hesam rastad

可能なすべての答えを得るために高速動的計画法アルゴリズムを実行する方法。20のエントリがあり、ベストアンサーが1行しか表示されないとします。結果としてすべてのエントリが表示され、繰り返しが許可されなくなるまで、最後まで実行して他のエントリも表示したいと思います。どうもありがとうございます。心から感謝する。ここにコードがあります:

#include <iostream>
#include <set>
#include <vector>
#include <map>
#include <utility>

using namespace std;

float W ,N; //N = olcu sayisi, W = profil boyu
vector<float> numbers; //stores the set of numbers

pair<float, multiset<float>> calc(float i, float j) //returns closest sum and best subset of the first i numbers for the target value j
{
    static map<pair<float, float>, pair<float, multiset<float>>> dp; //stores results to avoid repeated calculations

    pair<float, float> p(i, j); //pair for convenience

    if(i == 0) //base case
    {
        return make_pair(0, multiset<float>(
                                      {}));
    }

    auto findResult = dp.find(p);

    if(findResult != dp.end()) //check if already calculated
    {
        return findResult->second;
    }

    auto temp1 = calc(i - 1, j); //compute result if not using number

    if(numbers[i - 1] > j) //if current number is too big
    {
        return temp1;
    }

    auto temp2 = calc(i - 1, j - numbers[i - 1]); //compute result if using number
    temp2.first += numbers[i - 1];
    temp2.second.insert(numbers[i - 1]);

    pair<float, multiset<float>> result;
    if(temp1.first != temp2.first) //compare results and choose best
    {
        result = temp1.first > temp2.first ? temp1 : temp2;
    }
    else
    {
        result = temp1.second.size() < temp2.second.size() ? temp1 : temp2;
    }
    dp[p] = result;

    return result;
}

int main()
{
    cout << "sineklik sayisi: ";
    cin >> N;
    N = 2 * N;
    cout << "Profil olcusu: ";
    cin >> W;
    numbers.reserve(N); //avoid extra reallocations

    cout << "Olculeri giriniz: ";
    for(int i = 0; i < N; i++) //input loop
    {
        float temp;
        cin >> temp;
        numbers.push_back(temp);
    }

    pair<float, multiset<float>> result = calc(N, W); //calculate

    //output below
    cout << "The best possible sum is " << result.first << " Left behind is " << W - result.first << ", obtained using the set of numbers {";
    if(result.second.size() > 0)
    {
        cout << *result.second.begin();
        for(auto i = ++result.second.begin(); i != result.second.end(); i++)
        {
            cout << ", " << *i;
        }
    }
    cout << "}.\n";
}
BessieTheCookie

編集:これは私の古い答えの1つです。当時はそれほど上手ではありませんでしたが、今では、この問題に対してはるかに簡単で、高速で、メモリ消費の少ないソリューションがあることがわかりました。可能な限り最も近い合計のみを格納するテーブルでDPボトムアップを計算する場合、計算したテーブル値を使用して、後で再帰的にサブセットを再構築できます。

合計が目標値以下の可能な最大の合計に等しく、可能な限り少ない数の数値を含むすべての数値のセットを出力するソリューション:

#include <iostream>
#include <set>
#include <vector>
#include <map>
#include <utility>

using namespace std;

int N, W; //N = number of numbers, W = target sum
vector<int> numbers; //stores the set of numbers

pair<int, set<multiset<int>>> calc(int i, int j) //returns closest sum and best subset of the first i numbers for the target value j
{
    static map<pair<int, int>, pair<int, set<multiset<int>>>> dp; //stores results to avoid repeated calculations
    pair<int, int> p(i, j); //pair for convenience
    if(i == 0) //base case
    {
        set<multiset<int>> temp;
        temp.emplace();
        return make_pair(0, temp);
    }
    auto findResult = dp.find(p);
    if(findResult != dp.end()) //check if already calculated
    {
        return findResult->second;
    }
    auto temp1 = calc(i - 1, j); //compute result if not using number
    if(numbers[i - 1] > j) //if current number is too big
    {
        return temp1;
    }
    pair<int, set<multiset<int>>> temp2 = calc(i - 1, j - numbers[i - 1]), newtemp2; //compute result if using number
    newtemp2.first = temp2.first + numbers[i - 1];
    for(const auto k : temp2.second)
    {
        multiset<int> temp = k;
        temp.insert(numbers[i - 1]);
        newtemp2.second.insert(temp);
    }
    pair<int, set<multiset<int>>> *result;
    if(temp1.first != newtemp2.first) //compare results and choose best
    {
        result = temp1.first > newtemp2.first ? &temp1 : &newtemp2;
    }
    else if(temp1.second.begin()->size() != newtemp2.second.begin()->size())
    {
        result =
                temp1.second.begin()->size() < newtemp2.second.begin()->size() ? &temp1 : &newtemp2;
    }
    else
    {
        temp1.second.insert(newtemp2.second.begin(), newtemp2.second.end());
        result = &temp1;
    }
    dp.insert(make_pair(p, *result));
    return *result;
}

int main()
{
    cout << "Enter the number of numbers: ";
    cin >> N;
    cout << "Enter target sum: ";
    cin >> W;
    numbers.reserve(N); //avoid extra reallocations
    cout << "Enter the numbers: ";
    for(int i = 0; i < N; i++) //input loop
    {
        int temp;
        cin >> temp;
        numbers.push_back(temp);
    }
    pair<int, set<multiset<int>>> result = calc(N, W); //calculate
    //output below
    cout << "The best possible sum is " << result.first << ", which can be obtained using a set of "
            << result.second.begin()->size() << " numbers " << result.second.size()
            << " different ways:\n";
    for(const auto &i : result.second)
    {
        cout << '{';
        if(i.size() > 0)
        {
            cout << *i.begin();
            for(auto j = ++i.begin(); j != i.end(); ++j)
            {
                cout << ", " << *j;
            }
        }
        cout << "}\n";
    }
}

このソリューションでは、入力に表示された回数よりも多くの数値が出力に表示されることはありません。入力に複数回表示された場合でも、出力に1回だけ表示されるようにする場合は、マルチnumbersleftセットをセットに変更します。

#include <iostream>
#include <set>
#include <vector>
#include <map>
#include <utility>

using namespace std;

int N, W; //N = number of numbers, W = target sum
vector<int> numbers; //stores the set of numbers

pair<int, set<multiset<int>>> calc(int i, int j) //returns closest sum and best subset of the first i numbers for the target value j
{
    static map<pair<int, int>, pair<int, set<multiset<int>>>> dp; //stores results to avoid repeated calculations
    pair<int, int> p(i, j); //pair for convenience
    if(i == 0) //base case
    {
        set<multiset<int>> temp;
        temp.emplace();
        return make_pair(0, temp);
    }
    auto findResult = dp.find(p);
    if(findResult != dp.end()) //check if already calculated
    {
        return findResult->second;
    }
    auto temp1 = calc(i - 1, j); //compute result if not using number
    if(numbers[i - 1] > j) //if current number is too big
    {
        return temp1;
    }
    pair<int, set<multiset<int>>> temp2 = calc(i - 1, j - numbers[i - 1]), newtemp2; //compute result if using number
    newtemp2.first = temp2.first + numbers[i - 1];
    for(const auto k : temp2.second)
    {
        multiset<int> temp = k;
        temp.insert(numbers[i - 1]);
        newtemp2.second.insert(temp);
    }
    pair<int, set<multiset<int>>> *result;
    if(temp1.first != newtemp2.first) //compare results and choose best
    {
        result = temp1.first > newtemp2.first ? &temp1 : &newtemp2;
    }
    else if(temp1.second.begin()->size() != newtemp2.second.begin()->size())
    {
        result =
                temp1.second.begin()->size() < newtemp2.second.begin()->size() ? &temp1 : &newtemp2;
    }
    else
    {
        temp1.second.insert(newtemp2.second.begin(), newtemp2.second.end());
        result = &temp1;
    }
    dp.insert(make_pair(p, *result));
    return *result;
}

int main()
{
    cout << "Enter the number of numbers: ";
    cin >> N;
    cout << "Enter target sum: ";
    cin >> W;
    numbers.reserve(N); //avoid extra reallocations
    cout << "Enter the numbers: ";
    for(int i = 0; i < N; i++) //input loop
    {
        int temp;
        cin >> temp;
        numbers.push_back(temp);
    }
    pair<int, set<multiset<int>>> result = calc(N, W); //calculate
    //output below
    cout << "The best possible sum is " << result.first << ", which can be obtained using sets of "
            << result.second.begin()->size() << " numbers:\n";
    multiset<int> numbersleft;
    numbersleft.insert(numbers.begin(), numbers.end());
    for(const auto &i : result.second)
    {
        bool good = true;
        for(const int &j : i)
        {
            if(numbersleft.find(j) == numbersleft.end())
            {
                good = false;
                break;
            }
        }
        if(good)
        {
            for(const int &j : i)
            {
                numbersleft.erase(j);
            }
            cout << '{';
            if(i.size() > 0)
            {
                cout << *i.begin();
                for(auto j = ++i.begin(); j != i.end(); ++j)
                {
                    cout << ", " << *j;
                }
            }
            cout << "}\n";
        }
    }
}

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

動的計画法を使用して最も近いペアを選択するためのアルゴリズム

分類Dev

最大合計を見つけるための整数のnxn行列の動的計画法アルゴリズム

分類Dev

与えられた数までのすべての数を因数分解する高速アルゴリズム

分類Dev

アルゴリズムを逆に実行するための省略形

分類Dev

2つの並べ替えアルゴリズムを比較するために時間差を計算しようとしています

分類Dev

考えられるすべてのシナリオの可能性を計算するための柔軟なアルゴリズム

分類Dev

二分木で与えられた合計ですべてのパスを印刷するアルゴリズム

分類Dev

要素のすべての可能な順列を把握するためのアルゴリズムを設計するにはどうすればよいですか?

分類Dev

アルゴリズムの実行時間を修正するための支援

分類Dev

サブアレイクエリに高速に応答するための効率的なアルゴリズム

分類Dev

BigGraphにアルゴリズムを実装するための最良の方法

分類Dev

ヒストグラムに値を分散するための高速アルゴリズム?

分類Dev

すべての極大値を見つけるために最適化されたアルゴリズム

分類Dev

ピクセルの変化を検出するために必要な高速アルゴリズム

分類Dev

行を間隔に分割するためのアルゴリズム

分類Dev

この式を計算するための優れたアルゴリズム

分類Dev

メモ化を使用した動的計画法アルゴリズムの何が問題になっていますか?

分類Dev

数値のすべての桁を合計するアルゴリズム

分類Dev

有向非巡回グラフでパリンドロームを見つけるための動的計画法アルゴリズム

分類Dev

Pythonを使用して座標を計算するためにforループにLagrangeアルゴリズムを実装する方法

分類Dev

動的計画法アルゴリズムの開発に関連するステップ

分類Dev

JavascriptはPythonの同じアルゴリズムに異なる答えを与えています

分類Dev

合計の最大の組み合わせを実装するためのソートアルゴリズム

分類Dev

リスト内の連結されたすべての整数のペアの合計を見つけるための効率的なアルゴリズム

分類Dev

すべてのパス合計を見つけるためのこのアルゴリズムの時間計算量はどれくらいですか?

分類Dev

黄金比を計算するためのElispの効率的なアルゴリズム

分類Dev

アルゴリズムの実行時間を計算する方法は?

分類Dev

より高速なアルゴリズムを実装する

分類Dev

BFSアルゴリズムをより高速に実行するにはどうすればよいですか?

Related 関連記事

  1. 1

    動的計画法を使用して最も近いペアを選択するためのアルゴリズム

  2. 2

    最大合計を見つけるための整数のnxn行列の動的計画法アルゴリズム

  3. 3

    与えられた数までのすべての数を因数分解する高速アルゴリズム

  4. 4

    アルゴリズムを逆に実行するための省略形

  5. 5

    2つの並べ替えアルゴリズムを比較するために時間差を計算しようとしています

  6. 6

    考えられるすべてのシナリオの可能性を計算するための柔軟なアルゴリズム

  7. 7

    二分木で与えられた合計ですべてのパスを印刷するアルゴリズム

  8. 8

    要素のすべての可能な順列を把握するためのアルゴリズムを設計するにはどうすればよいですか?

  9. 9

    アルゴリズムの実行時間を修正するための支援

  10. 10

    サブアレイクエリに高速に応答するための効率的なアルゴリズム

  11. 11

    BigGraphにアルゴリズムを実装するための最良の方法

  12. 12

    ヒストグラムに値を分散するための高速アルゴリズム?

  13. 13

    すべての極大値を見つけるために最適化されたアルゴリズム

  14. 14

    ピクセルの変化を検出するために必要な高速アルゴリズム

  15. 15

    行を間隔に分割するためのアルゴリズム

  16. 16

    この式を計算するための優れたアルゴリズム

  17. 17

    メモ化を使用した動的計画法アルゴリズムの何が問題になっていますか?

  18. 18

    数値のすべての桁を合計するアルゴリズム

  19. 19

    有向非巡回グラフでパリンドロームを見つけるための動的計画法アルゴリズム

  20. 20

    Pythonを使用して座標を計算するためにforループにLagrangeアルゴリズムを実装する方法

  21. 21

    動的計画法アルゴリズムの開発に関連するステップ

  22. 22

    JavascriptはPythonの同じアルゴリズムに異なる答えを与えています

  23. 23

    合計の最大の組み合わせを実装するためのソートアルゴリズム

  24. 24

    リスト内の連結されたすべての整数のペアの合計を見つけるための効率的なアルゴリズム

  25. 25

    すべてのパス合計を見つけるためのこのアルゴリズムの時間計算量はどれくらいですか?

  26. 26

    黄金比を計算するためのElispの効率的なアルゴリズム

  27. 27

    アルゴリズムの実行時間を計算する方法は?

  28. 28

    より高速なアルゴリズムを実装する

  29. 29

    BFSアルゴリズムをより高速に実行するにはどうすればよいですか?

ホットタグ

アーカイブ