题意:
给定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; }
时间复杂度:空间复杂度: