关于背包删除操作的一二
背包问题,一般是将东西放入背包,如果我想要把一个东西删除去背包中,这个操作怎么转移呢?
感觉可以加上模板标签了。
看了题解的思路:
首先把所有东西合起来的情况肯定十分好求,现在我们就是要求去掉一个的情况。
首先我们先看一下如果最简单的背包怎么写
dp[0]=1;
for(int i=1;i<=n;++i){
for(int j=m;j>=v[i];--j){
dp[j]+=dp[j-v[i]];
}
}
这个肯定都会,那么我们现在再思考一个问题,我们如果把物品之间交换位置,那么答案是不是不会变?
既然是,那么我们假如说目前正在要删除第 \(x\) 个元素,我们现在把他放到最后一个,放到最后一个之后,我们现在当 \(i=n\) 时,是不是做了一次
for(int j=m;j>=v[i];--j){
dp[j]+=dp[j-v[i]];
}
将 \(x\) 放到最后后,如果有它,我们就要做一次这个,如果不做这个,答案是不是就是去掉它之后的答案。
那么这就很简单了,每次要算去掉 \(k\) 元素的时候,都假如它是最后一个元素,那么我们反过来做一次这个操作把它减掉就可以了。
代码如下:
#include <bits/stdc++.h>
#define debug puts("I love Newhanser forever!!!!!");
#define pb push_back
#define int long long
using namespace std;
template <typename T>inline void read(T& t){
t=0; register char ch=getchar(); register int fflag=1;
while(!('0'<=ch&&ch<='9')){if(ch=='-') fflag=-1;ch=getchar();}
while(('0'<=ch&&ch<='9')){t=t*10+ch-'0'; ch=getchar();} t*=fflag;
}
template <typename T,typename... Args> inline void read(T& t, Args&... args){read(t);read(args...);}
const int MAXN=2050;
int n,m,v[MAXN],dp[MAXN],ans[MAXN];
signed main(){
read(n,m);
for(int i=1;i<=n;++i) read(v[i]);
dp[0]=1;
for(int i=1;i<=n;++i){
for(int j=m;j>=v[i];--j){
dp[j]+=dp[j-v[i]];
dp[j]%=10;
}
}
for(int i=1;i<=n;++i){
memcpy(ans,dp,sizeof(dp));
for(int j=1;j<=m;++j){
if(j>=v[i]) ans[j]-=ans[j-v[i]],ans[j]%=10;
cout<<(ans[j]+1000000)%10;
}
cout<<endl;
}
return 0;
}