0-1背包问题

来源:互联网 发布:神行者定位软件 编辑:程序博客网 时间:2024/06/07 11:43

问题 A(1135): 【基础算法】0-1背包问题

时间限制: 1 Sec  内存限制: 64 MB
提交: 777  解决: 211

题目描述

有 n 件物品, 每件物品有一个价值和一个重量,分别记为: b1,b2, …bn w1,w2, …wn 其中所有的 重量wi 均为整数。 现有一个背包,其最大载重量为W,要求从这n件物品中任取若干件(这些物品要么被装入要么被留下)。问背包中装入哪些物品可使得所装物品的价值和最大?

输入

第1行:2个整数n(1<=n<=1000)和W(1<=W<=10000),分别表示物品的件数和背包的最大载重量。

第2-n+1行:每行2个用空格分开的整数,第i+1行的整数表示第i件物品的重量wi和价值bi(1<=bi,wi<=10000)。

输出

第1行:1个整数,表示背包所能装下的物品的最大总价值。

第2-?行:每行3个用空格分开的整数,i, wi, bi,分别表示最优解中的物品的编号、重量和价值。

样例输入

(如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)

4 52 33 44 55 6

样例输出

71 2 32 3 4



这道题和采药非常相似,没有看过采药的童鞋可以戳我查看



要看分析就去采药里看吧,这道题与采药唯一的不同点就是采药不输出方案,而这道题要。

————————————————分析———————————————————


如果要输出方案,那么我们就要另开一个数组。

假设我们已经求出来了能装下物品的最大总值(再申明一遍,没有看过采药的童鞋戳我查看),那么假设我们开了一个path数组。f[i][j]=f[i-1][j],那么就说明

f[i-1][j]没有用,所以我们标记一下。按照如此下去,就可以表示出所有装了的物品。

-----------------------------代码实现----------------------------------



#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Node
{
    int w,v;
}a[1005];
int n,W,f[1005][10005],path[1005];
void huisu(int i,int j)
{    
    if(i>0)
    {
        if(f[i][j]==f[i-1][j])
         {path[i]=0;huisu(i-1,j);
         }
        else
            if(j>=a[i].w&&f[i][j]==f[i-1][j-a[i].w]+a[i].v)
            {
                path[i]=1;
                huisu(i-1,j-a[i].w);
            }
    }
    return ;
}
int main()
{
    scanf("%d%d",&n,&W);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&a[i].w,&a[i].v);
        
    for(int i=1;i<=n;i++)
    {
        memcpy(f[i],f[i-1],sizeof(f[i]));
        for(int j=a[i].w;j<=W;j++)
            f[i][j]=max(f[i-1][j],f[i-1][j-a[i].w]+a[i].v);
    }
    printf("%d\n",f[n][W]);
    huisu(n,W);
    for(int i=1;i<=n;i++)
     if(path[i]==1)
      printf("%d %d %d\n",i,a[i].w,a[i].v);
    return 0;
}

戳我查看更多博客





原创粉丝点击