题目描述
设有1g、2g、3g、5g、10g、20g的砝码各若干枚(其总重≤1000)
输入格式
依次从轻到重输入各个砝码的个数
输出格式
输出方式:Total=N
(N表示用这些砝码能称出的不同重量的个数,但不包括一个砝码也不用的情况)
输入样例
1 1 0 0 0 0
输出样例
Total=3
解法
思路
本题有两种解题思路
-
采用多重背包模板,给定了t为1000的背包和N种体积为w[i]价值为v[i]的物品,各个物品有数量限制。本题只不过价值和体积是相等的,f[j]就用这些砝码能称出的小于j的最大重量,而j是从1开始增长,所以f[j]中存储了所有的情况,只需要对f[j]去重,剩下的重量种数就是Total
-
采用0/1背包模板,将n[i]个i复制出n[i]个,这n[i]个不再当成同一种,而是n[i]种体积和价值相同的物品。但是对于本题已经给出了各个砝码的费用和价值,就不太适合用这种方法了。
易错点
如果采用二维数组,f[i-1][j]到f[i][j]的复制条件容易丢
二维数组实现
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int main(){
int t=1000,N=6;
int f[7][1001]={},w[7]={0,1,2,3,5,10,20},v[7]={0,1,2,3,5,10,20},n[7]={};
for(int i=1;i<=N;i++){
cin>>n[i];
}
for(int i=1;i<=N;i++){
for(int j=1;j<=t;j++){
if(j<w[i]||n[i]==0){
f[i][j]=f[i-1][j];
continue;
}
for(int k=1;k<=n[i]&&k<=j/w[i];k++){
f[i][j]=max(f[i-1][j],f[i-1][j-k*w[i]]+k*v[i]);
}
}
}
sort(f[6]+1,f[6]+1001);
int Total=0;
for(int i=1;i<=1000;i++){
if(f[6][i]!=f[6][i-1])
Total++;
}
cout<<"Total="<<Total;
return 0;
}