P2347 [NOIP1996 提高组] 砝码称重
类似题目
题解1:01背包
#include<bits/stdc++.h>
using namespace std;
int w[]={0,1,2,3,5,10,20},a[1010],f[1010];
//f[i]是重量为i是否能称出,a[i]是每个砝码的重量
int main()
{
int n=0,ans=0,sum=0;
for(int i=1;i<=6;i++)
{
int t; cin>>t;
for(int j=1;j<=t;j++)
{
a[++n]=w[i]; //每个砝码都记录
sum+=w[i]; //总砝码的重量
}
}
f[0]=1; //初始化
for(int i=1;i<=n;i++)
{
for(int j=sum;j>=a[i];j--)
{
f[j]=f[j-a[i]]; //j-a[i]可以称出,则j也可以称出
}
}
for(int i=1;i<=sum;i++)
{
if(f[i]) ans++;
}
cout<<"Total="<<ans;
return 0;
}
题解2:bitset优化
#include<bits/stdc++.h>
using namespace std;
int w[]={0,1,2,3,5,10,20};
int main()
{
bitset<1010>f;
f[0]=1;
for(int i=1;i<=6;i++)
{
int t; cin>>t;
for(int j=1;j<=t;j++)
{
f|=f<<w[i]; //00011<<2=01100
//00011|01100=011111
}
}
cout<<"Total="<<f.count()-1; //把f[0]那个1删除
return 0;
}
P8742 [蓝桥杯 2021 省 AB] 砝码称重
解法1:01背包
#include<bits/stdc++.h>
using namespace std;
int n,a[105],f[105][100015]={0},sum=0,ans=0;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
}
for(int i=1;i<=n;i++)
{
for(int j=sum;j>=1;j--)
{
f[i][j]=f[i-1][j];
if(j==a[i]) f[i][j]=1;
else if(f[i-1][abs(j-a[i])]) f[i][j]=1;
else if(f[i-1][j+a[i]]) f[i][j]=1;
}
}
for(int i=1;i<=sum;i++)
{
if(f[n][i]) ans++;
}
cout<<ans;
return 0;
}
解法2:bitset
#include<bits/stdc++.h>
using namespace std;
int n,a[105],sum=0,ans=0;
int main()
{
bitset<100015>f;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
f[0]=1;
for(int i=1;i<=n;i++)
{
f|=f<<a[i]; //相当于a[i]对应的位置变成1;
}
for(int i=1;i<=n;i++)
{
f|=f>>a[i]; //相当于减法,在原有的基础上-a[i]的位置变成1;
}
cout<<f.count()-1;
return 0;
}