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

【CJWYH】RHL的背包题解(多重背包)

时间:2015-08-04 17:20:38      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:

题面

【问题描述】

CJ中学组织学生出去春游,作为学神的RHL自然不会放过这一大好时机,他有n种物品,第i件物品有c[i]个,每个体积为v[i],价值为w[i],RHL现在有一个体积为V的背包,他想让他带的东西价值之和最大,且体积之和不超过V,你能帮帮他吗?注意物体不能分割。

【输入】

输入文件名为bag.in,分为若干行。第一行包含两个正整数n,V。
第二行到第n+1行分别描述第i种物品的数量c[i],体积v[i],价值w[i]

【输出】

输出文件名为bag.out,一行输出一个整数,表示最大价值。

【输入输出样例】

bag.in
5 50
1 1 7
2 1 4
2 4 1
3 1 3
2 3 8
bag.out
42

【数据说明】

30%的数据满足n<=5,<=10,V<=100;
50%的数据满足n<=100,<=1000,V<=1000;
100%的数据满足n<=100,1<=c[i]<=10^5,1<=v[i]<=V<=10^4,1<=w[i]<=10^9

题解

方法1

分析

多重背包,数据很水,全是随机,DP裸过

代码

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
long long f[10000001]={0},n,V,v[1001],w[1001],c[1001];
int main()      
{
    freopen("bag.in","r",stdin);
    freopen("bag.out","w",stdout);
    cin>>n>>V;
    for (int i=1;i<=n;i++) cin>>c[i]>>w[i]>>v[i];
    for (int i=1;i<=n;i++)
      for (int j=V;j>=w[i];j--)
        for (int k=0;k<=min(c[i],j/w[i]);k++)
          f[j]=max(f[j-k*w[i]]+k*v[i],f[j]);
    cout<<f[V];
    return 0;
}

方法2

分析

如果出题人有意卡的话
——如所有物品体积为1,有很多个,背包容积很大
这个算法会爆
于是做优化处理
我们考虑1<=c[i]<=10^5
转换成二进制数在17位以内
我们可以把c[i]件物品拆分成最多17件,
按二进制位拆分
如15143个物品/(11101100100111)2拆成
(10000000000000)2=8192
(1000000000000)2=4096
(100000000000)2=2048
(1000000000)2=512
(100000000)2=256
(100000)2=32
(100)2=4
(10)2=2
(1)2=1
合起来正好为15143个
这样就转化为了01背包
复杂度O(NVlog2c[i])

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define N 105
#define M 2505
#define MaxV 10005
#define LL long long
#define oo (1<<30)
#ifdef WIN32
#define TAT "%I64d"
#else
#define TAT "%lld"
#endif
using namespace std;
LL f[MaxV],wm[M],ans=0;
int n,m,V,c[N],v[N],w[N],vm[M];
int main()
{
    int i,j;
    freopen("bag.in","r",stdin);
    freopen("bag.out","w",stdout);
    scanf("%d %d",&n,&V);
    for(i=1;i<=n;i++){
        scanf("%d %d %d",&c[i],&v[i],&w[i]);
        for(j=1;(j<<1)<=c[i];j<<=1)
            vm[++m]=j*v[i],wm[m]=1LL*j*w[i];
      vm[++m]=(c[i]-j+1)*v[i];
        wm[m]=1LL*(c[i]-j+1)*w[i];
      }
    for(i=1;i<=m;i++)
        for(j=V;j>=vm[i];j--)
            f[j]=max(f[j],f[j-vm[i]]+wm[i]);
    for(i=0;i<=V;i++)
        ans=max(ans,f[i]);
    printf(TAT,ans);
    return 0;
}

PS:RHL=R64=2013级的湖南OI界老大哥

版权声明:蒯代码有风险,爆0概不负责;随意转载,注明地址

【CJWYH】RHL的背包题解(多重背包)

标签:

原文地址:http://blog.csdn.net/qq_22141519/article/details/47278295

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