[洛谷P4141] 消失之物「背包DP」
暴力:暴力枚举少了哪个,下面套一个01背包
f[i][j]表示到了i物品,用了j容量的背包时的方案数,f[i][j]=f[i-1][j]+f[i-1][j-w[i]]O(n^3)
优化:不考虑消失的,先跑一个01背包,
定义g[i][j]表示i消失时,容量为j的方案数,g[i][j]=f[n][j]-不合法的
逆着过来就是g[i][j]-=g[i][j-w[i]
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 const int maxn=2005; 6 #define R register 7 int w[maxn],n,m; 8 int f[maxn][maxn],g[maxn][maxn]; 9 int main() 10 { 11 scanf("%d%d",&n,&m); 12 for(R int i=1;i<=n;++i) 13 scanf("%d",&w[i]); 14 f[0][0]=1; 15 for(R int i=1;i<=n;++i) 16 for(R int j=0;j<=m;++j){ 17 f[i][j]=f[i-1][j]%10; 18 if(j-w[i]>=0)(f[i][j]+=f[i-1][j-w[i]])%=10; 19 } 20 for(int i=1;i<=n;i++) 21 for(int j=0;j<=m;j++){ 22 g[i][j]=f[n][j]%10; 23 if(j-w[i]>=0)(g[i][j]-=g[i][j-w[i]])%=10; 24 }//第i个物品不选时,背包容量为j,若选i,则由g[i][j-w[i]](表示 不选i,背包有j-w[i])转移显然要减去 25 for(int i=1;i<=n;i++){ 26 for(int j=1;j<=m;j++) 27 printf("%d",(g[i][j]+10)%10); 28 puts(""); 29 } 30 }
愿你在迷茫时,记起自己的珍贵。