成魔之路−> 算法提高课题解
完全背包求方案数结论: f[i][j]=f[i−1][j]+f[i][j−v[i]]
推导过程:
因为,f[i][j]=f[i−1][j]+f[i−1][j−v]+f[i−1][j−2v]+…+f[i−1][j−sv]
f[i][j−v]= f[i−1][j−v]+f[i−1][j−2v]+…+f[i−1][j−sv]
所以,f[i][j]=f[i−1][j]+f[i][j−v]
思路:
-
1.状态表示
集合:从前 i 个物品中选,体积等于 j 的方案
属性:Count -
2.状态转移
f[i][j]=f[i−1][j]+f[i][j−v[i]] -
3.滚动数组
由于 f[i][j] 只需用到当前层和上一层,则结论可转化为:f[j]=f[j]+f[j−v[i]]
本题思路:
1. 易发现 b[i] 一定是从 a[1 ~ n] 中无法由其他数字构成的数字
2. 用完全背包判断该数字是否可有其他数字组成,如果不可以则记录
完整代码
#include<bits/stdc++.h>
using namespace std;
const int N = 110, M = 25010;
int n;
int a[N];
int f[M]; //从前 i 个物品里面选,体积等于 j 的方案数
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
sort(a,a+n); //排序
//多组测试数据初始化
memset(f,0,sizeof f);
f[0]=1;
int res=0;
for(int i=0;i<n;i++)
{
if(!f[a[i]]) res++; //该数字无法由其他数字组成
for(int j=a[i];j<=a[n-1];j++) f[j]+=f[j-a[i]];
}
cout<<res<<endl;
}
return 0;
}