[洛谷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 }
View Code
posted @ 2019-08-03 06:41  casun547  阅读(171)  评论(0编辑  收藏  举报