dp背包(二)

背包问题(二)

多重背包

对于一个容量为V的背包,我们有N种物品,每种num[i]个,消耗cost[i],价值val[i],求最大价值和

实际上,多重背包在01背包与完全背包之间
我们可以将num[i]个物品分成1个,2个…num[i]个
在这num[i]种选择中选择一种并且每种选择数量为一
其实这就是让我们选择num[i]个物品选几个
那么这个问题就被我们转化成01背包了
这可真棒!

三维代码//看到这里你有没有明白什么

#include<bits/stdc++.h>
using namespace std;
const int maxn=505,maxm=6005;
int v[maxn],w[maxn],s[maxn];
int dp[maxm];
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%d%d%d",&v[i],&w[i],&s[i]);
	for(int i=1;i<=n;i++){
		for(int j=m;j>=0;j--){
			for(int k=0;k<=s[i];k++){
				if(j>=k*v[i])
					dp[j]=max(dp[j],dp[j-k*v[i]]+w[i]*k);
			}
		}
	}
	printf("%d",dp[m]);
    return 0;
}

二进制优化代码

后续更新时间优化做法

例题 砝码称重

这道题我们的物品就是这6种砝码
我们可以求出组成x克的方案数,其它基本同模板

#include<bits/stdc++.h>
using namespace std;
const int maxn=10;
int a[maxn];
int d[maxn]={0,1,2,3,5,10,20};
int dp[1005];
int main()
{
	for(int i=1;i<=6;i++)scanf("%d",&a[i]);
	dp[0]=1;
	for(int i=1;i<=6;i++){
		if(a[i]==0)continue;
		for(int j=1000;j>=0;j--){
			for(int k=0;k<=a[i];k++){
				if(j>=d[i]*k)
					dp[j]+=dp[j-d[i]*k];
			}
		}
	}
	int ans=0;
	for(int i=1;i<=1000;i++){
		if(dp[i]>0)ans++;
	}
	printf("Total=%d",ans);
    return 0;
}

分组背包

一个容量为V的背包,现在有n件物品,重量是W[i],价值是C[i]。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求最大价值总和。

发布了28 篇原创文章 · 获赞 8 · 访问量 605

猜你喜欢

转载自blog.csdn.net/zty_ju/article/details/96499682