ftiasch 有 N 个物品, 体积分别是 W1, W2, …, WN。 由于她的疏忽, 第 i 个物品丢失了。 “要使用剩下的 N - 1 物品装满容积为 x 的背包,有几种方法呢?” – 这是经典的问题了。她把答案记为 Count(i, x) ,想要得到所有1 <= i <= N, 1 <= x <= M的 Count(i, x) 表格。
Input
第1行:两个整数 N (1 ≤ N ≤ 2 × 103) 和 M (1 ≤ M ≤ 2 × 103),物品的数量和最大的容积。
第2行: N 个整数 W1, W2, …, WN, 物品的体积。
Output
一个 N × M 的矩阵, Count(i, x)的末位数字。
Sample Input
3 2
1 1 2
Sample Output
11
11
21
HINT
如果物品3丢失的话,只有一种方法装满容量是2的背包,即选择物品1和物品2。
首先n个物品每个物品体积分别是w1 w2 w3求这个体积 一共多少种方案数可以购买 那么这是一个经典问题 那么题目要求我们输出不用某种物品 然后填满容积为x的方案数
怎么办 首先按照01背包 我求出没有哪件物品不被选的方案数
接下来 我针对每种物品 设cnt[i]表示填满i容积的背包我不需要 j号物品的方案数 那么对于cnt[i]=dp[i]-cnt[i-v[j]] 我的值就是总的方案数-i-v[j]不需要j号位置填的方案数 那么就相当于减去了需要v[i]物品填满的方案
#include<cstdio>
#include<cstring>
#define N 2200
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0;char ch=gc();
while(ch<'0'||ch>'9') ch=gc();
while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc();
return x;
}
int dp[N],n,m,cnt[N],a[N];
int main(){
//freopen("bzoj2287.in","r",stdin);
n=read();m=read();
for (int i=1;i<=n;++i)a[i]=read();dp[0]=1;
for (int i=1;i<=n;++i) for (int j=m;j>=a[i];--j) dp[j]+=dp[j-a[i]],dp[j]%=10;
for (int i=1;i<=n;++i){
memset(cnt,0,sizeof(cnt));cnt[0]=1;
for (int j=1;j<=m;++j){
if (j<a[i]) cnt[j]=dp[j];
else{
cnt[j]=dp[j]-cnt[j-a[i]];cnt[j]+=10;cnt[j]%=10;
}
}
for (int j=1;j<=m;++j) printf("%d",cnt[j]);puts("");
}
return 0;
}