看到这个题,自然而然想到用集合set来做,因为set本身就有去重的效果。
#include<bits/stdc++.h>
using namespace std;
int N;
int w;
set<int> s;
int main()
{
cin >> N;
for (int i = 1; i <= N; i++)
{
cin >> w;
vector<int> v(s.begin(), s.end()); //这里需要用vector来充当s的大小,因为下一步循环中要确保该次循环size的大小是不变的,循环内部就会增加s中的元素,会陷入死循环
for (int i = 0; i < v.size(); i++)
{
s.insert(w + v[i]);
if( abs(w - v[i])!=0 ) //注意取绝对值
s.insert(abs(w - v[i]));
}
s.insert(w);
}
cout << s.size() << endl; // 集合 s 中装了不同的 “组合重量” 的数量即是答案
return 0;
}
这种方法是比较方便的
这个问题主要的两个值就是砝码的个数和能通过加减实现的重量,而前一步可以取到的重量对下一步也有影响,那么又想到用动态规划来解决
设置一个二维数组,第一个维度是指使用了前n个砝码,第二个维度指可以取到的重量,当然并不是所有重量都可以取到,于是设为bool类型,来判断能否取到。能取到的最大重量一定是所有砝码的质量总和,所以循环到其重量之和就可以。
#include<bits/stdc++.h>
using namespace std;
int N;
int a[101];
bool ans[101][1000010];
int main()
{
int count;
cin >> N;
int tol = 0;
for (int i = 1; i <= N; i++)
{
cin >> a[i];
all += a[i]; //计算所有砝码总质量,用于循环次数
}
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= all; j++)
ans[i][j] = ans[i - 1][j];
//首先将i-1所能得到的j继承给i,因为能取到的质量只会在少一个砝码的情况下增加
for (int j = 1; j <= all; j++)
{
if (ans[i][j] == false)
{
if (a[i] == j) // 新砝码本身的重量
ans[i][j] = true;
else if (ans[i-1][j + a[i]] == true)
ans[i][j] = true;
else if (ans[i-1][abs(j - a[i])] == true) // dp背包思想
ans[i][j] = true;
}
}
}
for (int i = 1; i <= all; i++)
{
if (ans[N][i] == true) // 计数能取到的质量
count++;
}
cout << count << endl;
return 0;
}