揹包總結(未完待續)

1.定義

泛化物品是指該物品的價值與其體積存在一一對應的關係,即該物品的價值隨着體積的變化而變化,是一種函數關係。php

例如,在01揹包中,最後的答案數組其實就是一個泛化物品。ios

2運算

2.1 泛化物品的並

有泛化物品\(f,g\),他們的並是相同體積下價值的最大值。設f體積爲fv,g體積爲gv,把並後的泛化物品從新賦值給fc++

代碼:數組

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分別爲普通物體的體積,價值。函數

代碼:spa

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

2.3 泛化物品與泛化物品的合併

此過程要枚舉當前的整體積,和分給第一個泛化物品的體積,結果取最值。code

設f,g兩個泛化物品的合併爲h,fv,gv定義如上。get

代碼:string

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=1272it

能夠發現,每一組中其實都是一個泛化揹包,價值隨着體積的變化而變化。

把一個組轉化爲一個泛化揹包只有一點須要注意,若是體積有剩餘,價值與前面的同樣。詳細看代碼。

轉換完以後,對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);
	}

未完待續。

相關文章
相關標籤/搜索