①、確認子問題和狀態
01揹包問題須要求解的就是,爲了體積V的揹包中物體總價值最大化,件物品中第件應該放入揹包中嗎?(其中每一個物品最多隻能放一件)
爲此,咱們定義一個二維數組,其中每一個元素表明一個狀態,即前個物體中若干個放入體積爲揹包中最大價值。數組爲:,其中表示前件中若干個物品放入體積爲的揹包中的最大價值。
②、初始狀態
初始狀態爲和都爲0,前者表示前0個物品(也就是空物品)不管裝入多大的包中總價值都爲0,後者表示體積爲0的揹包啥價值的物品都裝不進去。
③、轉移函數c++
if (揹包體積j小於物品i的體積) f[i][j] = f[i-1][j] //揹包裝不下第i個物體,目前只能靠前i-1個物體裝包 else f[i][j] = max(f[i-1][j], f[i-1][j-Vi] + Wi)
用揹包表理解一下:數組
細心觀察,這個表格的每行表明第幾個物品,某列表明當前你的揹包有多大的容量,f[i][j]就是對應的這個二維表函數
代碼:優化
普通版代碼 #include<bits/stdc++.h>//萬能頭文件 #define ll long long using namespace std; const ll maxn=100; ll n,v,f[maxn][maxn]; ll c[maxn];//每一個物品佔用空間 ll w[maxn];//每一個物品的價值 int main() { cin>>n>>v; for(ll i=1;i<=n;i++) scanf("%lld",&c[i]); for(ll i=1;i<=n;i++) scanf("%lld",&w[i]); for(ll i=1;i<=n;i++)//第i個物品 for(ll j=v;j>=0;j--)//剩餘空間j { if(j >= c[i])//若是裝得下 f[i][j]=max( f[i-1][j-c[i]]+w[i],f[i-1][j]); else//若是裝不下 f[i][j]=f[i-1][j]; } cout<<f[n][v]<<endl;//輸出答案 }
空間優化版代碼 #include<bits/stdc++.h>//萬能頭文件 #define ll long long using namespace std; const ll maxn=100; ll n,v,f[maxn]; ll c[maxn];//每一個物品佔用空間 ll w[maxn];//每一個物品的價值 int main() { cin>>n>>v; for(ll i=1;i<=n;i++) scanf("%lld",&c[i]); for(ll i=1;i<=n;i++) scanf("%lld",&w[i]); for(ll i=1;i<=n;i++)//第i個物品 for(ll j=v;j>=1;j--)//剩餘空間j { if(f[j]<=f[j-c[i]]+w[i] && j-c[i]>=0 )//二維數組變一維數組 f[j]=f[j-c[i]]+w[i];//若是值得改變而且j的空間還裝得下就賦新值 } cout<<f[v]<<endl;//輸出答案 }