基础背包01(HDU2606,HUD3591)

来源:互联网 发布:sql是一种什么语言 编辑:程序博客网 时间:2024/06/06 00:18

背包,动态规划中一个很常见的类型。

有N 种物品和一个容量为V 的背包。放入第i 种物品耗费的费用是Ci,得到的价值是Wi。求解将哪些物品装入背包可使价值总和最大。

根据对于每种物品的数量要求,又可以将背包问题分为01背包(每种物品只有一个),完全背包(每种物品无限个),多重背包(每种物品特定数量个),分组背包(将物品分组,每组最多只有一个)等

接下来的两题,第一题是个简单01背包热身,第二题是个完全背包+多重背包的组合题


A.Bone Collector



思路:这是一道最基本的01背包问题,已知骨头价值和体积,装入特定体积背包,求最大价值。没有任何坑点,直接上手,算个热身。


#include <iostream>#include <cstdio>#include <algorithm>#include <vector>#include <cstring>using namespace std;const int maxn = 1e3+10;int w[maxn],p[maxn],f[maxn];int main(){    int t,n,v;    while(scanf("%d",&t)!=EOF)    {        while(t--)        {            scanf("%d%d",&n,&v);            for(int i=0;i<n;i++)            {                scanf("%d",&p[i]);            }            for(int i=0;i<n;i++)            {                scanf("%d",&w[i]);            }            memset(f,0,sizeof(f));            for(int i=0;i<n;i++)            {                for(int j=v;j>=w[i];j--)                {                    f[j] = f[j] > (f[j-w[i]]+p[i]) ? f[j] : (f[j-w[i]]+p[i]);                }            }            printf("%d\n",f[v]);        }    }    return 0;}



J.The trouble of Xiaoqian



思路:这题相对于第一题,明显加深。但从购买者来看,是个多重背包问题,然而由于找零问题,似乎瞬间复杂了许多。然而,其实,如果将购买者和售货员分开看,售货员就是个完全背包问题,这道题就被转化为完全背包和多重背包两个包的组合问题,两包容量相差值即为货物总价值,最终求和即可。

对于多重背包问题,如果直接转化成背包,多达100+的物品数O(n)会直接TLE,于是考虑优化,对于物品总价值超出包容量的情况,可以直接转化为完全背包,否则,按2次指数分解可以将时间复杂度降到O(ln(n))。

最后注意一下这是个最小价值问题,注意一下初始化赋值就好了


#include <iostream>#include <cstdio>#include <algorithm>#include <vector>#include <cstring>#include <climits>#include <cmath>using namespace std;const int maxn = 2e4+10;int v[110],c[110];int Xiaoqian[maxn],shopkeeper[maxn];//int pk[8] = {1,2,4,8,16,32,64,128};int main(){    int n,t,id = 0;    while(scanf("%d%d",&n,&t)!=EOF)    {        id++;        if(n==0&&t==0)        {            break;        }        for(int i=1;i<=n;i++)        {            scanf("%d",&v[i]);        }        for(int i=1;i<=n;i++)        {            scanf("%d",&c[i]);        }        for(int i=0;i<=maxn-5;i++)        {            Xiaoqian[i] = maxn;            shopkeeper[i] = maxn;        }        Xiaoqian[0] = 0;        shopkeeper[0] = 0;        /*for(int i=1;i<=n;i++)        {            for(int k=0;k<=log2(c[i]);k++)            {                for(int j=maxn-5;j>=pk[k]*v[i];j--)                {                    if(Xiaoqian[j]>Xiaoqian[j-pk[k]*v[i]] + pk[k])                    {                        Xiaoqian[j] = Xiaoqian[j-pk[k]*v[i]] + pk[k];                    }                }            }        }*/        for(int i=1;i<=n;i++)        {            if(c[i] * v[i] > maxn - 10)            {                for(int j=v[i];j<=maxn-5;j++)                {                    if(Xiaoqian[j]>Xiaoqian[j-v[i]] + 1)                    {                        Xiaoqian[j] = Xiaoqian[j-v[i]] + 1;                    }                }            }            else            {                int  k = 1;                while(k<=c[i])                {                    for(int j=maxn - 5;j>=k * v[i];j--)                    {                        if(Xiaoqian[j]>Xiaoqian[j-k*v[i]] + k)                        {                            Xiaoqian[j] = Xiaoqian[j-k*v[i]] + k;                        }                    }                    c[i] -= k;                    k <<= 1;                    //cout << k << endl;                }                for(int j=maxn - 5;j>=c[i] * v[i];j--)                {                    if(Xiaoqian[j]>Xiaoqian[j-c[i]*v[i]] + c[i])                    {                        Xiaoqian[j] = Xiaoqian[j-c[i]*v[i]] + c[i];                    }                }            }        }        for(int i=1;i<=n;i++)        {            for(int j=v[i];j<=maxn-5;j++)            {                if(shopkeeper[j]>shopkeeper[j-v[i]] + 1)                {                    shopkeeper[j] = shopkeeper[j-v[i]] + 1;                }            }        }        int maxcoin = maxn;        for(int i=t;i<=maxn-10;i++)        {            if(Xiaoqian[i] + shopkeeper[i-t] < maxcoin)            {                maxcoin = Xiaoqian[i] + shopkeeper[i-t];            }            //cout << Xiaoqian[i] << "*"<<shopkeeper[i]<<endl;        }        if(maxcoin > maxn-10)        {            maxcoin = -1;        }        printf("Case %d: %d\n",id,maxcoin);    }    return 0;}