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

01背包

时间:2019-03-10 17:55:47      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:ios   pre   有一个   struct   iostream   种类   ide   namespace   多重背包   

 

1

初始化的细节问题

我们看到的求最优解的背包问题题目中,事实上有两种不太相同的问法。有的题目要求“恰好装满背包”时的最优解,有的题目则并没有要求必须把背包装满。一种区别这两种问法的实现方法是在初始化的时候有所不同。

如果是第一种问法,要求恰好装满背包,那么在初始化时除了f[0]为0其它f[1..V]均设为-∞,这样就可以保证最终得到的f[N]是一种恰好装满背包的最优解。

如果并没有要求必须把背包装满,而是只希望价格尽量大,初始化时应该将f[0..V]全部设为0。

为什么呢?可以这样理解:初始化的f数组事实上就是在没有任何物品可以放入背包时的合法状态。如果要求背包恰好装满,那么此时只有容量为0的背包可能被价值为0的nothing“恰好装满”,其它容量的背包均没有合法的解,属于未定义的状态,它们的值就都应该是-∞了。如果背包并非必须被装满,那么任何容量的背包都有一个合法解“什么都不装”,这个解的价值为0,所以初始时状态的值也就全部为0了。

 

2.

多重背包可以分成n个  也可以用二进制来优化:

技术图片
#include <bits/stdc++.h>
 
using namespace std;
 
struct E
{
    int w;  //体积
    int v;  //重量
} lis[2001];
 
int dp[101];
 
int main()
{
    int T,n,m;
    int p,h,k;
    int i,j;
    int index,c;
    scanf("%d%d",&n,&m);                //n表示容量,m表示种类
    index = 0;  //拆分后物品总数
    for( i=1; i<=m; i++)
    {
        c = 1;
        scanf("%d%d%d",&p,&h,&k);       //p表示价格,h表示重量,k表示大米袋数。
        while( k-c>0)
        {
            k -= c;
            lis[++index].w = c*p;
            lis[index].v = c*h;
            c *= 2;
        }
        lis[++index].w = p*k;  //补充不足指数的差值
        lis[index].v = h*k;
    }
    for( i=0; i<=n; i++) dp[i]=0;
    for( i=1; i<=index; i++)   //对拆分后的物品进行0-1背包
    {
        for( j=n; j>=lis[i].w; j--)
            dp[j] = max( dp[j],dp[j-lis[i].w]+lis[i].v);
    }
        printf("%d\n",dp[n]);
    return 0;
}
View Code

 

3.

打印物品:

技术图片
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int dp[10005];
bool path[105][10005];
int c[10005],w[10005];
int main()
{
    int N,V;
    while (cin>>V>>N)
    {
        memset(path,0,sizeof(path));
        memset(dp,0,sizeof(dp));
        for (int i = 1;i <= N;++i) cin>>c[i]>>w[i];
        for (int i = N;i >= 1;--i)
        {
            for (int j = V;j >= c[i];--j)
            {
                if (dp[j] < dp[j-c[i]]+w[i])
                {
                    dp[j] = dp[j-c[i]]+w[i];
                    path[i][j] = 1;
                }
            }
        }
        cout<<dp[V]<<endl;
        puts("-----------------------------------------");
        for (int i = 1,j = V;i <= N&&j > 0;i++)
        {
            if (path[i][j])
            {
                printf("%d ",i);
                j -= c[i];
            }
        }
        puts("");
    }
    return 0;
}
View Code

 

 

 

大牛总结的非常好:

https://www.kancloud.cn/kancloud/pack/70133

 

01背包

标签:ios   pre   有一个   struct   iostream   种类   ide   namespace   多重背包   

原文地址:https://www.cnblogs.com/bxd123/p/10505885.html

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