1426: 逃亡的准备
时间限制: 1 Sec 内存限制: 128 MB提交: 13 解决: 7
您该题的状态:已完成
[提交][状态][讨论版]
题目描述
每个人小时候都有自己的理想,但随着时间推移,渐渐的大多数人的理想变成了金钱.地位.面子... 于是大多数人 就变成了传说中的俗人。但我们的中中始终有自己的梦想,他要 环 游 世 界! 在20XX年X月X日中中开始环游世 界的准备工作.他开始准备自己的行囊
中中背包的容积为m ,中中有n样有用的东西 ,每样东西都有自己的价值Wi,和体积Vi ,每一样物品有Ni个 (Ni=0时表示有无限多个),于是乎我们的问题就是(你应该已经猜到了)...中中能带走的 东西的最大价值。
30%数据满足 1 <= m,n <=1000
100%数据满足 1 <=m,n <= 10000
中中背包的容积为m ,中中有n样有用的东西 ,每样东西都有自己的价值Wi,和体积Vi ,每一样物品有Ni个 (Ni=0时表示有无限多个),于是乎我们的问题就是(你应该已经猜到了)...中中能带走的 东西的最大价值。
30%数据满足 1 <= m,n <=1000
100%数据满足 1 <=m,n <= 10000
输入
第 1 行: N,M--物品的种类和背包的容积
第 2-N+1 行: Vi,Wi,Pi--三个整数:每个物品的体积.价值.个数
第 2-N+1 行: Vi,Wi,Pi--三个整数:每个物品的体积.价值.个数
输出
单独的一行在给定的限制里可能得到的最大的价值。
样例输入
5 50
1 1 50
2 4 3
48 49 1
1 51 1
3 3 3
样例输出
106
题中描述有ni=0时可以无线取,典型的混合背包,但是队友当时没注意,用了多重背包,由此可见,后台数据都没有ni=0的情况,完全背包不考虑也行。但是用普通的多重背包,队友好像时间超限了,混合背包模板在我别的博客也有,就不贴了。
多重背包优化做法:
//求指定体积V下的最大价值
#include <iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
using namespace std;
#define ll long long
int dp[10050];
int wi[10050];//价值
int vi[10050];//体积
int pi[10050];//个数
int Value[111110];
int size[111110];
int main()
{
//count存储分解完后的物品总数
//Value存储分解完后每件物品的价值
//size存储分解完后每件物品的体积
int n,v;
scanf("%d%d",&n,&v);
int count=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&vi[i],&wi[i],&pi[i]);
for(int j=1; j<=pi[i]; j<<=1)
{
//<<右移1位,相当于乘2
Value[count]=j*wi[i];
size[count++]=j*vi[i];
pi[i]-=j;
}
if(pi[i]>0)
{
Value[count]=pi[i]*wi[i];
size[count++]=pi[i]*vi[i];
}
}
//经过上面对每一种物品的分解,
//现在Value[]存的就是分解后的物品价值
//size[]存的就是分解后的物品体积
//count就相当于原来的 n
//下面就直接用01背包算法来解
memset(dp,0,sizeof(dp));
for(int i=0; i<count;i++)
for(int j=v;j>=size[i];j--)
if(dp[j]<dp[j-size[i]]+Value[i])
dp[j]=dp[j-size[i]]+Value[i];
printf("%d\n",dp[v]);
return 0;
}
---------更新----------
上面的多重背包做法,数组大小开的时候至少比题目要求大十倍,Value、size数组更要大很多,不然会超时,很难把握。今天做了一道HDU 2844多重背包,此模板时间也是快接近TEl了,主要是数组不好控制,发现了下面这个模板,数组按题意开,时间也比上个模板快。
//指定体积内的最大值
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int dp[100007],n,m,a[10005],b[10005],c[10005],count;
void zeropack(int cost,int value)
{//01背包选择
for(int i=m;i>=cost;i--)
dp[i]=max(dp[i],dp[i-cost]+value);
}
void completepack(int cost,int value)
{//完全背包选择
for(int i=cost;i<=m;i++)
dp[i]=max(dp[i],dp[i-cost]+value);
}
void multipack(int cost,int value,int num)
{//进行判断,const :体积;value:价值;num:个数
if(num*cost>=m)
{
completepack(cost,value);
return;
}
int k=1;
while(k<num)
{
zeropack(k*cost,k*value);
num-=k;
k*=2;
}
zeropack(num*cost,num*value);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d%d%d",&a[i],&b[i],&c[i]);
memset(dp,0,sizeof(dp));
count=0;
for(int i=1;i<=n;i++)
{
multipack(a[i],b[i],c[i]);
}
printf("%d\n",dp[m]);
return 0;
}
2018.05.12