Loading

背包总结(未完待续)

1.定义

泛化物品是指该物品的价值与其体积存在一一对应的关系,即该物品的价值随着体积的变化而变化,是一种函数关系。

例如,在01背包中,最后的答案数组其实就是一个泛化物品。

2运算

2.1 泛化物品的并

有泛化物品\(f,g\),他们的并是相同体积下价值的最大值。设f体积为fv,g体积为gv,把并后的泛化物品重新赋值给f

代码:

	int v=Max(fv,gv);
	for(int i=1;i<=v;i++) f[i]=Max(f[i],g[i]);

2.2泛化物品与普通物品的合并

此过程类似于01背包,f为泛化物品,fv为其最大体积,v,c分别为普通物体的体积,价值。

代码:

for(int i=1;i<=fv;i++) f[i+v]=Max(f[i+v],f[i]+c);

2.3 泛化物品与泛化物品的合并

此过程要枚举当前的总体积,和分给第一个泛化物品的体积,结果取最值。

设f,g两个泛化物品的合并为h,fv,gv定义如上。

代码:

	for(int i=0;i<=v;i++)
		for(int j=0;j<=i;j++)
			h[i]=Max(h[i],g[j]+f[i-j]);

3例题

3.1 分组背包

http://ybt.ssoier.cn:8088/problem_show.php?pid=1272

可以发现,每一组中其实都是一个泛化背包,价值随着体积的变化而变化。

把一个组转化为一个泛化背包只有一点需要注意,如果体积有剩余,价值与前面的一样。详细看代码。

转换完之后,对n个泛化背包进行合并。输出结果。有了泛化背包这个概念后明显好理解了许多。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<deque>
#include<cstdlib>
#include<ctime>
#define dd double
#define ll long long
#define ull unsigned long long
#define N 11
#define M 201
using namespace std;

int v,n,t;
int h[N][M];

inline int Max(int a,int b){
	return a>b?a:b;
}

int main(){
	scanf("%d%d%d",&v,&n,&t);
	for(int i=1;i<=n;i++){
		int w,c,p;
		scanf("%d%d%d",&w,&c,&p);
		h[p][w]=Max(h[p][w],c);
	}
	for(int i=1;i<=t;i++){
		int now=0;
		for(int j=0;j<=v;j++){
			now=Max(now,h[i][j]);
			h[i][j]=now;
		}
	}
//	for(int i=1;i<=t;i++){
//		for(int j=0;j<=v;j++) printf("%d ",h[i][j]);
//		printf("\n");
//	}
	for(int i=2;i<=t;i++){
		for(int j=v;j>=0;j--)
			for(int k=0;k<=j;k++)
				h[i][j]=Max(h[i][j],h[i-1][k]+h[i][j-k]);
//		printf("new i:%d  ",i);
//		for(int j=0;j<=v;j++) printf("%d ",h[i][j]);
//		printf("\n");
	}
		
	printf("%d",h[t][v]);
	return 0;
}

3.2 01背包

http://ybt.ssoier.cn:8088/problem_show.php?pid=1267

	for(int i=1;i<=n;i++)
	{
		int w,c;
		scanf("%d%d",&w,&c);
		for(int j=m;j>=w;j--)
		{
			f[j]=max(f[j],f[j-w]+c);
		}
	}

3.3完全背包

http://ybt.ssoier.cn:8088/problem_show.php?pid=1268

	for(int i=1;i<=n;i++)
	{
		int w,c;
		scanf("%d%d",&w,&c);
		for(int j=w;j<=m;j++)
		{
			f[j]=max(f[j],f[j-w]+c);
		}
	}

3.4混合背包

http://ybt.ssoier.cn:8088/problem_show.php?pid=1270

	for(int i=1;i<=n;i++)
	{
		int w,c,p;
		scanf("%d%d%d",&w,&c,&p);
		if(p==1) a[++tail].intt(w,c,1);
		else if(p==0) a[++tail].intt(w,c,0);
		else
		{
			for(int j=1;j<=p;j*=2)
    		{
	    		p-=j;
	    		a[++tail].intt(j*w,j*c,1);
	    	}
	    	if(p) a[++tail].intt(p*w,p*c,1);
		}
	}
	
	for(int i=1;i<=tail;i++)
	{
		if(a[i].p==1)
		    for(int j=m;j>=a[i].w;j--)
		        f[j]=max(f[j],f[j-a[i].w]+a[i].c);
		else
		    for(int j=a[i].w;j<=m;j++)
		        f[j]=max(f[j],f[j-a[i].w]+a[i].c);
	}

未完待续。

posted @ 2021-02-19 18:46  hyl天梦  阅读(62)  评论(0编辑  收藏  举报