web-dev-qa-db-ja.com

繰り返しのないナップザック:ゴールドの最大量

CourseraのAlgorithmicToolboxコースから。

問題の紹介

あなたは金の延べ棒のセットを与えられ、あなたの目標はあなたのバッグにできるだけ多くの金を入れることです。各バーのコピーは1つだけであり、各バーについて、それを取得することも、取得しないこともできます(したがって、バーの一部を取得することはできません)。

問題の説明

仕事。与えられた????金の延べ棒、容量のバッグに収まる金の最大重量を見つけますか????。入力フォーマット。入力の最初の行には容量が含まれていますか????ナップザックの数と数????金の延べ棒の。次の行には????が含まれています整数???? 0、???? 1、。 。 。 、????????-1金の延べ棒の重さを定義します。

制約。 1≤???? ≤10^ 4; 1≤???? ≤300; 0≤???? 0、。 。 。 、????????-1≤10^ 5。

出力フォーマット。容量のナップザックに収まる金の最大重量を出力しますか????。

C++での私の解決策:

const int WEIGHT_MAX = 1000 + 1;
const int ITEMS_COUNT_MAX = 300 + 1;

int optimal_weight(int W, const vector<int> &w) {
  int weights[ITEMS_COUNT_MAX][WEIGHT_MAX];
  const int w_size = w.size();

  for (int i = 0; i <= w_size; i++) {
    for (int j = 0; j <= W; j++) {      
        if (i==0 || j==0) 
          weights[i][j] = 0;
        else if (w[i - 1] <= j) 
          weights[i][j] = std::max(w[i - 1] + weights[i - 1][j - w[i - 1]],  weights[i - 1][j]);
        else
          weights[i][j] = weights[i - 1][j];
    }
  }

  int result = weights[w_size][W];
  return result;
}

入力用

10 3
1 4 8

...次の2D行列を生成します。

0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1
0 1 1 1 4 5 5 5 5 5 5
0 1 1 1 4 5 5 5 8 9 9

しかし、14年生のテストのうち9番目は合格していません。グレーダーは、使用した入力を提供しません。

誰かが私に解決策の可能な警告を指摘できますか?

更新[Mattのおかげで解決] :ローカルスタックサイズはサイズ10001х301の配列を保持するのに十分ではないため、メモリをヒープに割り当てる必要があります。実際、スタックに割り当てようとすると、セグメンテーション違反エラーが発生します。

int optimal_weight(int W, const vector<int> &w) {
  const int w_size = w.size();
  int** weights = new int* [w_size + 1];

  for (int i = 0; i <= w_size; i++) {
    weights[i] = new int[W + 1];
  }

  for (int i = 0; i <= w_size; i++) {
    for (int j = 0; j <= W; j++) {      
        if (i==0 || j==0) {
          weights[i][j] = 0;
        }
        else if (w[i - 1] <= j) 
          weights[i][j] = std::max(w[i - 1] + weights[i - 1][j - w[i - 1]],  weights[i - 1][j]);
        else
          weights[i][j] = weights[i - 1][j];
    }
  }

  int result = weights[w_size][W];

  for (int i = 0; i < w_size; i++) {
    delete[] weights[i];
  }

  delete[] weights;

  return result;
}
2

計算は問題ありませんが、最大の重みは10000で、行列は1001までしか上がらないため、バッファオーバーランが発生します。

そもそもマトリックスをスタックに割り当てるのは良いことではありません。その問題を修正すると、さらに悪化します。

また、この問題を解決するために2次元行列は実際には必要ありません。

アクセス可能な重みのソートされたリストを維持してみてください。 [0]から始めて、各アイテムに新しくアクセス可能な重みを追加します。

2
Matt Timmermans