bzoj 2287(背包dp)

来源:互联网 发布:房子平面设计软件手机 编辑:程序博客网 时间:2024/06/15 16:15

传送门

题解:

设f[i]为装满i的容量的方案数,可以按01背包的方法O(nm)预处理。

设g[i][j]表示不用i,装满j的容量的方案数。

对于每个i:

若i<v[j],则g[i][j]=f[j]

否则g[i][j]=f[j]-g[i][j-v[i]]

由于每个物品单独考虑互不影响,所以g数组可以去掉第一维。


P.S.听说可以用什么分治背包?以后再说。。。

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int MAXN=2004;int n,m;int v[MAXN],f[MAXN],g[MAXN];inline int read() {int x=0;char c=getchar();while (c<'0'||c>'9') c=getchar();while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();return x;}int main() {//freopen("bzoj 2287.in","r",stdin);f[0]=1;n=read(),m=read();for (int i=1;i<=n;++i) {v[i]=read();for (int j=m;j>=v[i];--j)f[j]=(f[j]+f[j-v[i]])%10;}for (int i=1;i<=n;++i) {for (int j=0;j<=m;++j) {if (j<v[i]) g[j]=f[j];else g[j]=(f[j]-g[j-v[i]]+10)%10;if (j) printf("%d",g[j]);}puts("");}return 0;}