码迷,mamicode.com
首页 > 其他好文 > 详细

acm——背包问题

时间:2015-10-11 00:19:08      阅读:256      评论:0      收藏:0      [点我收藏+]

标签:

一、背包问题分类:

  我觉得简单的背包问题分为两类:一是01背包问题:每个物品只有拿或者不拿两种选项;另一种就是非01背包问题,每种物品的重量只要不超过背包的最大容量,可以拿任意多个。

  背包问题还可以按照求最大或者最小分类;

  还可以根据是否一定要充满背包分成充满和不充满;

二、背包问题的一般递推:

  我只知道一种方法:假设我们要求价值最大的值;背包的容量为w;每件物品i的价值为val[i],重量为vol[i];我们先定义f[j]为背包容量为j时,所容物品的价值最大值;所以我们得到f[j]的递推公式:

                            f[j]=max(f[j],f[j-vol[i]]+val[i]);

  当然我们不能马上使用,要根据具体的情况选择不同的方式表达。

  1.首先是一般背包最大值问题,每种物品的重量只要不超过背包的最大容量,可以拿任意多个,同时需要充满背包;

    设有n件物品,背包的容量为w,每件物品i的价值为val[i],重量为vol[i],f[j]为背包容量为j时,所容物品的价值最大值;我们可以这么写:

for(i=1;i<=n;i++)
        {
            for(j=vol[i];j<=w;j++)
            {
                f[j]=max(f[j-vol[i]]+val[i],f[j]);
            }
        }

  2.01背包最大值问题,每个物品只有拿或者不拿两种选项,同时需要充满背包;

    设有n件物品,背包的容量为w,每件物品i的价值为val[i],重量为vol[i],f[j]为背包容量为j时,所容物品的价值最大值;我们可以这么写:

for(i=1;i<=n;i++)
        {
            for(j=w;j>=vol[i];j--)
            {
                f[j]=max(f[j-vol[i]]+val[i],f[j]);
            }
        }

    这里注意,因为是01背包问题,每件物品只能拿一件,所以j从w开始递减,这样保证了每件物品只拿一件。

    同时注意,上面所说的开始时要初始化memset(f,0,sizeof(f));如果背包不能充满,则f[w]=0;

  3.一般背包最大值问题,每种物品的重量只要不超过背包的最大容量,可以拿任意多个,同时不需要充满背包;这里只要一点点改动即可:

for(i=1;i<=n;i++)
        {
            for(j=vol[i];j<=w;j++)
            {
                m=max(f[j-vol[i]]+val[i],f[j]);
                if(f[j]<m)
                     f[j]=m;
            }
        }   

  4.同理,01背包最大值问题,不需要充满背包时:

for(i=1;i<=n;i++)
        {
            for(j=w;j>=vol[i];j--)
            {
                m=max(f[j-vol[i]]+val[i],f[j]);
                if(m>f[j])
                     f[j]=m;
            }
        }

  求最小时,只要将上面的max换成min即可。

这里,以hdu的两道题为:

    hdu2602

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
    int t,n,w,f[1001],vol[1001],val[1001] ,m,i,j;
    scanf("%d",&t);
    while(t--)
    {
        m=0;
        memset(f,0,sizeof(f));
        scanf("%d %d",&n,&w);
        for(i = 1 ; i <= n ; i++)
        scanf("%d",&val[i]);
        for(i = 1 ; i <= n ; i++)
        scanf("%d",&vol[i]);
        for(i = 1 ; i <= n ; i++)
        {
            for(j = w ; j >= vol[i] ; j--)
            {
                m=f[j-vol[i]]+val[i];
                if(f[j]<m)
                    f[j]=m;
            }
        }
        printf("%d\n",f[w]);
    }
    return 0;
}

  hdu1114

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define min(a,b) ((a)<(b)?(a):(b))
int main()
{
    int t,n,w,f[10010],vol[1001],val[1001] ,m,i,j,a,b;
    scanf("%d",&t);
    while(t--)
    {
        m=0;
        scanf("%d %d",&a,&b);
        w=b-a;
        for(i=0;i<=w;i++)
            f[i]=500000000;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
            scanf("%d%d",&val[i],&vol[i]);
            f[0]=0;
        for(i=1;i<=n;i++)
        {
            for(j=vol[i];j<=w;j++)
            {
                f[j]=min(f[j-vol[i]]+val[i],f[j]);
            }
        }
        if(f[w]==500000000)
            printf("This is impossible.\n");
        else
            printf("The minimum amount of money in the piggy-bank is %d.\n",f[w]);
    }
    return 0;
}

 

acm——背包问题

标签:

原文地址:http://www.cnblogs.com/vallzey/p/4868573.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!