题意:
给定n种砝码,重量互不相等。
每种砝码对应的数量为
。
现在要用这些砝码去称物体的重量(放在同一侧),问能称出多少种不同的重量。
注:称重重量包括 0 。
方法一:
动态规划
思路:转化为01背包问题。
将 砝码之和 即看成 背包的体积,又看成 背包装载的价值。
当 增加的价值==消耗的体积 时,即恰满足条件,答案计数加一。
#include <bits/stdc++.h>
using namespace std;
int a[15],b[15],dp[1000005];
int main(){
int n;
while(cin >> n){
memset(dp,0,sizeof(dp));
int sum=0;
for(int i=0;i<n;i++)//每种砝码的重量
cin >> a[i];
for(int i=0;i<n;i++)//每种砝码的数量
cin >> b[i],sum+=b[i]*a[i];//sum统计砝码的重量总和
for(int i=0;i<n;i++){
for(int j=0;j<b[i];j++){
for(int k=sum;k>=a[i];k--){//01背包
dp[k]=max(dp[k],dp[k-a[i]]+a[i]);
}
}
}
int res=0;
for(int i=0;i<=sum;i++)
if(dp[i]==i)//如果价值等于空间,则满足条件
res++;
cout << res << endl;
}
return 0;
}
时间复杂度:
空间复杂度:![]()
方法二:
set去重
思路:利用set去重的思想。首先,set集合初始化:一个元素0。
遍历每一个砝码,将集合中的数值都加上这个砝码的重量。
因为集合有去重的功能,所以最后集合的大小即为答案。
#include <bits/stdc++.h>
using namespace std;
int a[15],b[15];
int main(){
int n;
while(cin >> n){
for(int i=0;i<n;i++)
cin >> a[i];//每种砝码的重量
for(int i=0;i<n;i++)
cin >> b[i];//每种砝码的数量
unordered_set<int> res;
res.insert(0);//初始化
for(int i=0;i<n;i++){
for(int j=0;j<b[i];j++){//遍历每个砝码
unordered_set<int> t(res);
for(auto x:t){
res.insert(x+a[i]);//添加并去重
}
}
}
cout << res.size() << endl;
}
return 0;
}
时间复杂度:
空间复杂度:![]()



京公网安备 11010502036488号