0
点赞
收藏
分享

微信扫一扫

背包九讲模板

可以参考这篇博文:https://www.baidu.com/link?url=L8KfGu87UT1dX38ZBjBTRDkHOFZwUsWtesJekk1c1C8FH2UqKws4iSb3NvrUkO7jTHdE-Vnzdh7y2O5IUhw7vgPv9Qh-eFEvrQAIKoN5KKK&wd=&eqid=9001344500120700000000036227f42f

题库在这:题库 - AcWing

一、01背包

for(int i=1;i<=n;i++) for(int j=0;j<=m;j++){
	dp[i][j]=dp[i-1][j];
	if(j-v[i]>=0) dp[i][j]=max(dp[i][j],dp[i-1][j-v[i]]+w[i]);
}
for(int i=0;i<n;i++) for(int j=m;j>=v[i];j--)
    dp[j]=max(dp[j],dp[j-v[i]]+w[i]);

二、完全背包

for(int i=1;i<=n;i++) for(int j=0;j<=m;j++){
	dp[i][j]=dp[i-1][j];
	if(j-v[i]>=0) dp[i][j]=max(dp[i][j],dp[i][j-v[i]]+w[i]);
}
for(int i=0;i<n;i++) for(int j=v[i];j<=m;j++)
	dp[j]=max(dp[j],dp[j-v[i]]+w[i]);

三、多重背包

法一:01背包(O(nmk),准确来讲是 O(nΣki))

for(int i=0;i<n;i++) for(int k=1;k<=s[i];k++) for(int j=m;j>=v[i];j--)
    dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
for(int i=0;i<n;i++) for(int j=m;j>=v[i];j--) for(int k=1;k<=s[i]&&k*v[i]<=j;k++)
    dp[j]=max(dp[j],dp[j-k*v[i]]+k*w[i]);

法二:二进制优化的01背包(O(nmlogk),准确来讲是O(nΣlogki))

#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
int n,m,dp[200005];
vector<int> v,w;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++){
		int vv,ww,s;
		scanf("%d %d %d",&vv,&ww,&s);
		for(int k=1;s;k=k<<1){
			k=min(k,s);
			s-=k;
			v.push_back(vv*k);
			w.push_back(ww*k);
		}
	}
	for(int i=0;i<v.size();i++) for(int j=m;j>=v[i];j--)
		dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
	printf("%d\n",dp[m]);
	return 0;
}

法三:单调队列优化的01背包(终极模板,O())

四、混合背包问题

五、二维费用的背包问题

六、分组背包问题

七、有依赖的背包问题

#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
int n,m,root,v[105],w[105],dp[105][105];
vector<int> sons[105];
void dfs(int i){
	for(int j=v[i];j<=m;j++) dp[i][j]=w[i];//想放子树,必先装根 
	for(int son:sons[i]){
		dfs(son);
		for(int j=m;j>=v[i];j--)
			for(int k=j-1;k>=v[i];k--)//>=v[i]:得从装过根的本轮小包转移过来 
				dp[i][j]=max(dp[i][j],dp[i][k]+dp[son][j-k]);
	}
}
int main(){
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++){
		int fa;
		scanf("%d %d %d",&v[i],&w[i],&fa);
		if(fa==-1) root=i;
		else sons[fa].push_back(i);
	}
	dfs(root);
	printf("%d\n",dp[root][m]);//注意这里不要因为习惯错写成 dp[n][m] 
	return 0;
}

八、背包问题求方案数

九、求背包问题的具体方案

举报

相关推荐

0 条评论