【NOIP模板①】经典DP——背包问题

关于背包,我相信任何一个对OI小有涉猎的人都有所耳闻,在NOIP前夕,特将各类基础背包模板整理后呈现于此,以供OIer们能有所便利。

首先介绍一下背包问题的类型,背包问题大致分为三类:01背包,完全背包,多重背包。

其中01背包是基础中的基础,几乎任何背包类问题的状态转移方程都是由01背包延伸而来的。它的大致题意是:有n个物品,每个物品有一个价值w[i],和重量c[i]。然后你的背包载重量是有限的V,因此需要选择总价值尽量大的物品。

而完全背包则是01背包的强化版——每个物品都有无限个了,再做出选择。而多重背包则更进一步:每个物品是有限多的个数,以此做出抉择。

在本文中并不会详细分析背包问题及其状态转移方程,仅仅是给出实现的模板,读者可以根据需要自由改动。关于背包类更详细的解答,可以在本文末的链接中下载由崔添翼(Tianyi Cui)所著的背包问题九讲中细细品味。

// 以下实现均使用了滚动数组技巧
void ZeroOnePack(int D[],int w,int c)    //01背包,三个参数分别代表DP数组,物品价值,物品重量,V代表背包容量,以下相同
{
    for(int i = V;i >= c;i--)
        D[i] = max(D[i],D[i-c]+w);
}

void CompletePack(int D[],int w,int c)  //完全背包
{
    for(int i = c;i <= V;i++)
        D[i] = += D[i-1];
}

void CompletePack_solutions(int D[],int w,int c)  //求在完全背包的题设下,有多少种方法可以装满背包
{
    for(int i = c;i <= V;i++)
        D[i] = max(D[i],D[i-c]+w);
}

void MultiplePack(int D[],int w,int c,int num)  //多重背包,num代表物品数目
{
    if(c * num >= V)
    {
        CompletePack(D[],w,c);
        return ;
    }
    int k = 1;
    while(k < num)
    {
        ZeroOnePack(D[],w*k,c*k);
        num -= k;
        k *= 2;
    }
    ZeroOnePack(D[],w*num,c*num);
    return ;
}
//以01背包为例,在主程序中,可以写出如下代码
for(int i = 1;i <= n;i++)
    ZeroOnePack(D,w[i],c[i]);


《背包问题九讲》链接:http://pan.baidu.com/s/1qW9Hed2(若链接失效请及时提醒)


你可能感兴趣的:(DP,经典DP,背包问题,动态规划,C++)