詳細なナップザック問題(C ++) - 01リュックサック

01ナップザック問題

件名の説明:

N項目Vとバックパックの容量があります。各項目は、一度だけ使用することができます。アイテムのボリュームはI〜V、値のwiです。
これはバッグにアイテムを解決する、これらの項目の総容積はバックパックの容量、及び最大の合計値を超えることはできません。
最大出力値。

入力フォーマット:

二つの整数N、Vの最初の行はそれぞれ、スペースで区切られた、及び物品の数は、ボリュームのバックパック。次いで、N行、二つの整数viは、wiはそれぞれスペースで区切られた各列、及びアイテムのi番目の値の量が存在します。

分析:

一つだけ、各項目の、あなたは入れてホールドするように選択することができます。状態遷移方程式を得るために、動的プログラミングを使用するのは簡単ですので。

f[i][j]=max{f[i-1][j],f[i-1][j-v[i]]+w[i]} // f[i][j]表示前i件物品恰放入一个容量为j的背包可以获得的最大价值。

状態遷移方程式を用いて、我々は、直接01ナップザック問題の二次元配列の溶液を書き込むことができます。

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 1010;

int n,m;

int v[N],w[N];

int f[N][N];

int main()
{
    cin>>n>>m;
    for(int i = 1;i<=n;i++){
        cin>>v[i]>>w[i];
    }
    for(int i =1;i<=n;i++){
        for(int j = 0;j<=m;j++){
            f[i][j] = f[i-1][j];//不含第i个物品
            if(j>=v[i]) f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]);
        }
    }
     cout<<f[n][m]<<endl;
     return 0;
}

時間とプロセスの空間計算量はO(nm)です。、時間計算量が最適化されていない、我々は状態遷移方程式、F [i]は[]およびF [I-1] []のみ関連することを観察することができるO(N)に空間的複雑度を最適化し続けることができます。その後、我々は一次元配列F [0 ... V] Fを表すために使用することができる[I] [0 ... V]、状態遷移方程式は、次のとおり

f[j] = max(f[ j ],f[ j-v[i] ]+w[i]);

一次元転送方程式maxの(F [J]、F [JV [I] + [I] W) と二次元状態遷移方程式最大{F [I-1]〜 [J]、F [I-1 ] [JV [I] + W [I]} 我々は順次列挙ではなく、M降順列挙を必要とするバックパックのサイズに対応します。なぜ?なぜ逆列挙は、あなたがこの記事を見ることができhttps://blog.csdn.net/xiajiawei0206/article/details/19933781
または独自のデータは、それがある方法で、順次列挙を押して何をシミュレート理解しやすいです。
以下01バックパック一次元アレイ最適化されたコードです。

// 一维数组优化版
#include<iostream>
#include<algorithm>

using namespace std;

const int N =1010;

int n,m;
int v[N],w[N];
int f[N];

int main(){
    cin>>n>>m;
    
    for(int i=1;i<=n;i++){
        cin>>v[i]>>w[i];
    }
    for(int i=1;i<=n;i++){
        for(int j=m;j>=v[i];j--){
            f[j] = max(f[j],f[j-v[i]]+w[i]);
        }
    }
    cout<<f[m]<<endl;
    return 0;
}

私たちは、直接01ナップザック問題のテンプレートを取得することができます

//m为背包大小.cost为代价,weight为价值
void ZeroOnePack(int cost,int weight)
{
    for(int i=m;i>=cost;i--)
        f[i] = max(f[i],f[i-cost]+weight);
}

ナップザック問題は、問題の変異体の数を聞かれることがあり、一部はちょうど満たされたバックパックを必要とし、いくつかは聞いてませんでした。どちらも初期設定が異なっています。あなただけのバックパックを埋めるために必要がある場合は、Fを除いて、初期化[0] 0他のF [1 ... V]が-∞に設定されている、ちょうど埋めを必要とせず、F [0 ... V]がすべて設定されている場合、それが初期化されるべき0。

出版元の記事 ウォンの賞賛0 ビュー18

おすすめ

転載: blog.csdn.net/weixin_42648202/article/details/104481096