题目描述
有N件物品和一个体积是C的背包。需要把一些物品装到背包里使得剩下的物品无法再放入,求方案数。每件物品有一个体积Vi。
输入
本题包含多组测试数据。第一行输入一个整数,表示数据组数。接下来对于每组数据的第一行是两个整数,N,C。然后N个整数Vi,表示每个物品的体积,1<=C<=1000,1<=N<=30。
输出
对于每个测试数据,输出2个整数,第一个表示数据编号,第二个是题目要求的方案数。
样例输入
2
6 25
8 9 8 7 16 5
30 250
1 2 3 4 5 6 7 8 9 10 11
12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
样例输出
1 15
2 16509438
题解
01背包变种题。
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=30+20; const int maxv=1000+5; int T,n,m,v[maxn],sum[maxn],dp[maxv],Case=1; template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int main(){ read(T); while(T--){ read(n),read(m); for(int i=0;i<=m;i++) dp[i]=0; for(int i=1;i<=n;i++) read(v[i]); sort(v+1,v+1+n); for(int i=1;i<=n;i++) sum[i]=sum[i-1]+v[i]; if(v[1]>m){ cout<<Case++<<" "<<"0"<<endl; continue; } int ans=0;dp[0]=1; for(int i=n;i>=1;i--){ int left=m-sum[i-1]; for(int j=max(0,left-v[i]+1);j<=left;j++) ans+=dp[j]; for(int j=m;j>=v[i];j--) dp[j]+=dp[j-v[i]]; } cout<<Case++<<" "<<ans<<endl; } return 0; }