01背包

01背包问题求解思路

  ①、确认子问题和状态 
  01背包问题需要求解的就是,为了体积V的背包中物体总价值最大化,件物品中第件应该放入背包中吗?(其中每个物品最多只能放一件) 
  为此,我们定义一个二维数组,其中每个元素代表一个状态,即前个物体中若干个放入体积为背包中最大价值。数组为:,其中表示前件中若干个物品放入体积为的背包中的最大价值。 
  ②、初始状态 
  初始状态为和都为0,前者表示前0个物品(也就是空物品)无论装入多大的包中总价值都为0,后者表示体积为0的背包啥价值的物品都装不进去。 
  ③、转移函数

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)

用背包表理解一下:

01背包_第1张图片

细心观察,这个表格的每行代表第几个物品,某列代表当前你的背包有多大的容量,f[i][j]就是对应的这个二维表

代码:

普通版代码
#include//万能头文件
#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<//输出答案

}
空间优化版代码
#include//万能头文件
#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<//输出答案

}

 

 

 

 

你可能感兴趣的:(01背包)