動的プログラミング:0-1ナップザック問題(C ++)

動的プログラミング:0-1ナップザックの問題

動的プログラミングの一般的な手順:

  1. 問題構造分析
  2. 再帰的な関係の確立
  3. ボトムアップ計算
  4. 最良のソリューション追跡

例0-1ナップザックの問題

(件名:https://www.acwing.com/problem/content/description/2/)

タイトル説明
N個のアイテムと容量Vのバックパックがあります。各アイテムは1回のみ使用できます。

アイテムのボリュームは、私がVである私は、Wの値であり、I

これらのアイテムの合計ボリュームがバックパックの容量を超えず、合計値が最大になるように、バックパックにパックするアイテムを見つけます。
最大値を出力します。

入力フォーマット
最初の行のスペースで区切られた2つの整数NとVは、それぞれアイテムの数とバックパックのボリュームを示します。

次に、N行があり、各行にはそれぞれスペースで区切られた2つの整数V i、W i、およびアイテムのi番目の値のボリュームがあります。

出力形式
最大値を表す整数を出力します。

データ範囲
0 <N、V≤10000
<vi、wi≤1000

入力例
4 5
1 2
2 4
3 4
4 5

サンプル出力
8

問題分析
特定のサイズのバックパックの場合、合計値の最大値を見つけます。各アイテムには2つの選択ケースのみがあり、選択されていない場合は、2つのケースの合計値を比較します。

f [i] [j]は、最初のiアイテムのみを見るという意味です。合計ボリュームがjの場合、最大合計値はいくつですか。
結果= max {f [n] [0〜V]}

f [i] [j]:
1.i番目の項目f [i] [j] = f [i-1] [j]を選択しないでください。2。i番目の項目f [i] [j]を
選択してください。= f [i-1] [jv [i];

f [i] [j] = max {1,2}の2つの場合で、最も大きく、最も大きいものを選択します。

初期化:f [0] [0] = 0;

ここに写真の説明を挿入

コード1

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1010;
int n,m;	//n表示物体个数,m表示背包容量 
int f[N][N]; 
int v[N], w[N]	//v[N], w[N] 分别表示每个物品的体积和价值 

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

2次元アレイ状にf[N][N]二次元配列の最適化に基づくf[N][N]ために最適化されたf[N]各外部ループ、F [m]は一回更新する。表現、jのi番目の値と記事の数の前にバックパックの最大容量は、前記;
ここに写真の説明を挿入

コード2

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1010;
int n,m;	//n表示物体个数,m表示背包容量 
int f[N]; 	//表示背包体积为j时前i个物品的最大价值为多少 
int v[N], w[N]	//v[N], w[N] 分别表示每个物品的体积和价值 

int main(){
    
    
	cin >> n >> m;
	for(int i=0; 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]);		//f[j]滚动记录最优解 
		} 
		
	cout << f[m] << endl;	
	return 0;
} 

おすすめ

転載: blog.csdn.net/qq_44524918/article/details/108992114