通天之分组背包 题解

版权声明:八月炊火的博客如需转载请注明出处 https://blog.csdn.net/qq_34990731/article/details/83384972

题目
知识点: 背包DP
讲解:
对于这一类题有个名字叫分组背包,是九大背包之一,而这一个也不会太难,我们现在来看看。
这一题我们其实可以看做0/1背包,然后加一个每组只可以取1个的条件,我们发现如果加了这个条件,那么我们用0/1背包的做法就会有后效性,所有后效性都可以通过加状态维数来消除(个人认为,如果有反例欢迎留言),我们发现后效性和组别有关所以我们就可以这样,对于一组里面的每一个我们都枚举计算一遍,这样我们就可以保证每个答案每组最多取一个,这样这个后效性就解决了。
代码:

#include<iostream>
#include<cstdio>
using namespace std;
struct beibao
{
	int v,w;//v是价值,w是重量 
}AC[1000];
int dp[1000],a[1000][1000],V,N,T;
int main ()
{
	int ans=0;
	scanf("%d %d",&V,&N);
	for (int i=1;i<=N;i++)
	{
	  	int p;
		scanf("%d %d %d",&AC[i].w,&AC[i].v,&p);
		a[p][0]++;//我们用a数组存对于每一组的每一个对应的编号 
		a[p][a[p][0]]=i;
		T=max(p,T);//T表示组数,因为没告诉所以自己计算 
	}
	for(int i=1;i<=T;i++)//组数,我们放在最外围可以保证这个组里面的最多取1个 
		for(int j=V;j>=0;j--)//重量 
			for(int k=1;k<=a[i][0];k++)//从每一组第一个数开始递推 
				if(AC[a[i][k]].w<=j)//判断数组是否可以转移 
				    dp[j]=max(dp[j],dp[j-AC[a[i][k]].w]+AC[a[i][k]].v);
	for(int i=1;i<=V;i++)//对于每个容量取最大 
		ans=max(ans,dp[i]);
	printf("%d",ans);
	return 0;
}

如果有疑问的欢迎留言。
祝大家可以AC。

猜你喜欢

转载自blog.csdn.net/qq_34990731/article/details/83384972