揹包問題(1)-01揹包

揹包問題(Knapsack problem)是一種組合優化的NP完全問題。問題可以描述爲:給定一組物品,每種物品都有自己的重量和價格,在限定的總重量內,我們如何選擇,才能使得物品的總價格最高。問題的名稱來源於如何選擇最合適的物品放置於給定揹包中。相似問題經常出現在商業、組合數學,計算複雜性理論、密碼學和應用數學等領域中。也可以將揹包問題描述爲決定性問題,即在總重量不超過W的前提下,總價值是否能達到V?它是在1978年由Merkle和Hellman提出的。

01揹包
問題描述:
給定n種物品和一揹包。物品i的重量是wi,其價值爲vi,揹包的容量爲C。問應如何選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大?

算法分析:

二維做法
用一個數組f[i][j]表示,在只有i個物品,容量爲j的情況下揹包問題的最優解,那麼當物品種類變大爲i+1時,最優解是什麼?第i+1個物品可以選擇放進揹包或者不放進揹包(這也就是0和1),假設放進揹包(前提是放得下),那麼f[i+1][j]=f[i][j-w[i+1]+v[i+1];如果不放進揹包,那麼f[i+1][j]=f[i][j]。
這就得出了狀態轉移方程:

f[i+1][j]=max(f[i][j],f[i][j-w[i+1]+v[i+1])
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=2e2+10;
int f[40][N],w[40],v[40],n,C; 
int main()
{
	//fre();
	scanf("%d%d",&C,&n);
	for(int i=1;i<=n;i++) scanf("%d%d",&w[i],&v[i]);
	for(int i=1;i<=n;i++) 
		for(int j=C;j>0;j--)
		{
			if(w[i]<=j)	f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);	
			else f[i][j]=f[i-1][j];
		}
	printf("%d",f[n][C]);			
	return 0;
}

一維做法:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=2e2+10;
int f[N],w[40],v[40],n,C; 
int main()
{
	//fre();
	scanf("%d%d",&C,&n);
	for(int i=1;i<=n;i++) scanf("%d%d",&w[i],&v[i]);
	for(int i=1;i<=n;i++) 
		for(int j=C;j>=w[i];j--)
			if(w[i]<=j)	f[j]=max(f[j],f[j-w[i]]+v[i]);	
	printf("%d",f[C]);			
	return 0;
}


其他揹包問題:
揹包問題(2)-完全揹包

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章