複数のナップサック問題1
4を取得してから
制限時間:1秒
スペース制限:64MB
タイトル説明:
N個のアイテムとVの容量を持つバックパックがあります。
i番目のアイテムには最大でsi個のアイテムがあり、各アイテムのボリュームはviで、値はwiです。
アイテムの総量がバックパックの容量を超えないように、どのアイテムがバックパックにロードされているかを解決し、合計値が最大になります。
最大値を出力します。
入力フォーマット:
最初の行の2つの整数NとVはスペースで区切られ、それぞれオブジェクトの数とバックパックのボリュームを示します。
次に、N行があり、それぞれに3つの整数vi、wi、siがあり、スペースで区切られ、i番目のアイテムの量、値、および数量を示します。
出力フォーマット:
最大値を表す整数を出力します。
データ範囲:
0 <N、V <= 100
0 <vi、wi、si <= 100
入力サンプル:
4 5
1 2 3
2 4 1
3 4 3
4 5 2
サンプル出力:
10
この問題は、dp 2次元配列で解決できますが、最適化を実行すると、配列を1次元配列に開くことができ、製品の操作ごとに、バックパックを後ろから前に更新するだけで十分です。
01バックパックに基づいて、このトピックの製品ごとに複数のアイテムが存在する場合があります。たとえば、そのような製品が3つある場合、それらを3つの異なる製品として扱い、01バックパック方式を使用します。
一次元:
#include<iostream>
using namespace std;
int N,V,dp[105]; //dp是状态数组,表示背包在某个容量目前能装下的最多价值
int main(){
cin>>N>>V;
for(int i = 1;i <= N;++i){
int a,b,c;cin>>a>>b>>c; //商品的体积和价值
while(c--)
for(int j = V;j >= a;--j)
if(dp[j] < dp[j - a] + b) //如果在此时装入该物品,价值会提升,那么就装入
dp[j] = dp[j - a] + b;
}
cout<<dp[V];
return 0;
}
二次元:
#include<iostream>
#include<algorithm>
using namespace std;
int vi[10005];
int wi[10005];
int dp[10005][105];
int main(){
int n,v,k = 0,a,b,c;
cin>>n>>v;
for(int i = 1;i <= n;i++){
cin>>a>>b>>c;
while(c--){
vi[++k] = a;
wi[k] = b;
}
}
n = k;
for(int i = 1; i <= n;i++)
for(int j = 1;j <= v;j++){
if(j < vi[i])
dp[i][j] = dp[i - 1][j];
else{
dp[i][j] = max(dp[i - 1][j],dp[i - 1][j - vi[i]] + wi[i]);
}
}
cout<<dp[n][v];
return 0;
}