1.dfs
AcWing 3417. 砝码称重(闫式dp/dfs) - AcWing
2.dp
#include<iostream>
#include<cmath>
using namespace std;
int N;
int a[101];
int cnt;
bool ans[101][1000010];
int main()
{
cin >> N;
int tol = 0;
for (int i = 1; i <= N; i++)
{
cin >> a[i];
tol += a[i];
}
for (int i = 1; i <= N; i++)
{
// 继承上一轮的结果。因为对于 “前 i 个砝码能凑成的所有重量的集合”, 则前 i+1 个砝码一定也能凑到
for (int j = 1; j <= tol; j++)
ans[i][j] = ans[i - 1][j];
for (int j = 1; j <= tol; j++) // 只需要遍历到 tol
{
if (ans[i][j] == false)
{
if (a[i] == j) // 手段一:新加入砝码的重量 正好为 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) // 手段三(背包的思想)
ans[i][j] = true;
}
}
}
for (int i = 1; i <= tol; i++) // 从重量为 1 的情况开始计数
{
if (ans[N][i] == true) // 对于前 N 个砝码, 能凑成重量为 i 的情况的话, 计数就 + 1
cnt++;
}
cout << cnt << endl;
return 0;
}
3.queue 暴力模拟
对已经产生的重量,放入queue
#include <bits/stdc++.h>
using namespace std;
int st[100010];
int main()
{
queue<int> q;
int n,t;
cin>>n;
int ans=0;
q.push(0);//重量开始是0
st[0]=1;
while(n--){
cin>>t;
queue<int> qq;
//当前砝码和已经有的重量组合
while(!q.empty()){
int w=q.front();
q.pop();
qq.push(w);//q的队头移到qq,才能继续遍历q
//现有重量w
int a=w+t;//砝码放左边重量
int b=abs(w-t);//砝码放右边重量,记得加绝对值
if(st[a]==0){
st[a]=1;
qq.push(a);
}
if(st[b]==0){
st[b]=1;
qq.push(b);
}
}
q=qq;
}
cout<<q.size()-1<<endl;//q里面有一个0,这个数我们不需要
return 0;
}