01揹包

01揹包問題求解思路

  ①、確認子問題和狀態 
  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;//輸出答案

}
相關文章
相關標籤/搜索