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

题面

【问题描述】

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概不负责;随意转载,注明地址

时间: 2024-10-03 13:20:23

【CJWYH】RHL的背包题解(多重背包)的相关文章

背包之01背包、完全背包、多重背包详解

首先说下动态规划,动态规划这东西就和递归一样,只能找局部关系,若想全部列出来,是很难的,比如汉诺塔.你可以说先把除最后一层的其他所有层都移动到2,再把最后一层移动到3,最后再把其余的从2移动到3,这是一个直观的关系,但是想列举出来是很难的,也许当层数n=3时还可以模拟下,再大一些就不可能了,所以,诸如递归,动态规划之类的,不能细想,只能找局部关系. 1.汉诺塔图片 (引至杭电课件:DP最关键的就是状态,在DP时用到的数组时,也就是存储的每个状态的最优值,也就是记忆化搜索) 要了解背包,首先得清楚

背包整理(01背包,完全背包,多重背包,分组背包)(待更新)

目录 01背包 优化(空间) 完全背包 优化 多重背包 优化 分组背包 01背包 有N件物品和一个容量为V的背包.第i件物品的价格(即体积,下同)是w[i],价值是c[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 对于每个物品,我们有两种选择:把这个物品放进背包还是不放. d[i][v]表示前i件物品,恰放入容积为v的背包时的价值总和. 状态转移方程为 \[d[i][v] = \max(d[i - 1][v],d[i - 1][v - w[i]] + c[i

dp背包问题/01背包,完全背包,多重背包,/coin change算法求花硬币的种类数

一步一步循序渐进. Coin Change 具体思想:给你 N元,然后你有几种零钱S={S1,S2...,Sm} (每种零钱数量不限). 问:凑成N有多少种组合方式  即N=x1 * S1+x2*S2+...+xk*Sk (xk>=0,k=1,2..m) 设有f(x)中组合方式 有两种解答(自底向上回溯): 1.不用第m种货币   f(N,m-1) 2.用第m种货币 f(N-Sm,m) 总的组合方式为f(N,m)=f(N,m-1)+f(N-Sm,m) anything is nonsense,s

【板+背包】多重背包 HDU Coins

http://acm.hdu.edu.cn/showproblem.php?pid=2844 [题意] 给定n种价值为Ci,个数为Wi的硬币,问在1~V中的这些数中哪些数能由这些硬币组成? [思路] 多重背包,二进制优化,时间复杂度为O(V*log∑ni) [Accepted] 1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<

有关货币问题的动态规划题目--有关01背包,完全背包,多重背包

背包dp:参考背包九讲以及给出一些题目 01背包 (先枚举物品,再逆序枚举容量) 给定n件物品和一个容量为V的背包,每件物品的体积是w[i],价值是va[i](1<=i<=n),求在不超过背包的容量的情况下,怎么选择装这些物品使得得到的价值最大? 例如:有5件物品,体积分别是{2,2,6,5,4},价值分别是{6,3,5,4,6} 递归式:F(i,v)=max(F(i-1,v), F(i-1,v-w[i])+va[i]),其中F(i,v)表示把前i种物品恰放入背包容量为v时取得的最大价值 把这

01背包模板、全然背包 and 多重背包(模板)

转载请注明出处:http://blog.csdn.net/u012860063 贴一个自觉得解说不错的链接:http://www.cppblog.com/tanky-woo/archive/2010/07/31/121803.html 模版就直接贴代码: 01背包模板: /* 01背包问题 01背包问题的特点是,">每种物品仅有一件.能够选择放或不放. 01背包问题描写叙述: 有N件物品和一个容量为V的背包. 第i件物品的重量是c[i],价值是w[i]. 求解将哪些物品装入背包可使这些物品

背包问题(01背包,完全背包,多重背包)

转自:http://www.cnblogs.com/daoluanxiaozi/archive/2012/05/06/2486105.html 背包问题,经典有背包九讲. 01背包 不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,只有一张钞票),为了防止自己在战斗中频繁的死掉,他决定给自己买一些道具,于是他来到了地精商店前. 死亡骑士:"我要买道具!" 地精商人:"我们这里有三种道具,血瓶150块一个,魔法药200块一个,无敌药水350块一个." 死亡骑士

01背包,完全背包,多重背包,混合背包

详见大牛背包九讲(下载地址:http://pan.baidu.com/s/1b9edXW) 1 //Class->物品种类,val->价值,room->所占空间,num->物品数量,Room->背包容量 2 3 #include<stdio.h> 4 const int maxn = 1e6; 5 6 int bag[maxn]; 7 int Room; 8 9 void zero_one_bag(int,int); //01背包 10 void complete

【背包专题】C - The trouble of Xiaoqian hdu3591【混合背包:多重背包+完全背包】

In the country of ALPC , Xiaoqian is a very famous mathematician. She is immersed in calculate, and she want to use the minimum number of coins in every shopping. (The numbers of the shopping include the coins she gave the store and the store backed

【背包问题】0-1背包、完全背包、多重背包、混合三种背包、二位费用背包、分组背包

一.0-1背包问题 输入:第一行物品的个数n,第二行背包的质量m,随后n行每行给出每个物品的重量和价值,每种物品只有一个. 输出:背包可以达到的最大价值 样例输入: 5 10 1 5 2 4 3 3 4 2 5 1 样例输出: 14 动态规划的过程中需要逆序,因为如果不是逆序那么 当i=0的时候 f[0]=0; f[1]=max(f[1],f[1-w[0]]+v[0])=5; f[2]=max(f[2],f[2-w[0]]+v[0])=10; f[3]=max(f[3],f[3-w[0]]+v[