关于背包删除操作的一二

背包问题,一般是将东西放入背包,如果我想要把一个东西删除去背包中,这个操作怎么转移呢?

例题

感觉可以加上模板标签了。

看了题解的思路:

首先把所有东西合起来的情况肯定十分好求,现在我们就是要求去掉一个的情况。

首先我们先看一下如果最简单的背包怎么写

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;
}
posted @ 2022-07-10 19:28  Mercury_City  阅读(339)  评论(0编辑  收藏  举报